0 * 1 =ā¦
So that leaves the question of why youāre hitting twiceā¦ Do you have multiple TryHit animation events on the animation? Is there still a Hit animation event in your animation? Does your TryHit have multiple damage calls?
nope, weāre hitting twice because thereās a āWeaponDamageā and an āAttackForceā both exerting forceā¦ I like the weapon damage because of the easier name and that itās directly accessible from when we are creating the weapon, but attack force is there as well, and I couldnāt be more baffled down the line
Anyway, Iām still trying to figure out the sudden character generator bug before we get back into adding new stuff
Force is what flows through all living beings, and can be characterized as light or dar-- erā¦ sorry, wrong movie.
Damage is applied to health and doesā¦ .damage
Force is applied to ForceReciever and should doā¦ no damageā¦
you really love classic movies, donāt you? May the 4th be with you
OK so to recall before I go back to my annoying bug (which I am really clueless of how to solve, but Iām tryingā¦):
- Attack Force is the force applied to the player, when they hit someone
- Hit force is the reaction force to push them back
ā¦ Right?
Thatās correct
good day to you too kind sir
Fair enough, for now Iāll let it be. Still trying to figure out what went wrong with my Synty modelsā¦ - link
did I miss out on something with the Impact statesā¦? When both me and my enemy try to return to idle state after we received a hit, we both literally freeze pretty much foreverā¦ As if the āHandleForceCompleted()ā function never unsubscribed to begin withā¦ (and yes, I made sure it was in both āEnterā and āExitā states of both the Impact States)
In āEnemyImpactState.csā (SPOILER), this script:
using UnityEngine;
namespace RPG.States.Enemies {
public class EnemyImpactState : EnemyBaseState
{
private readonly int ImpactHash = Animator.StringToHash("Impact");
public EnemyImpactState(EnemyStateMachine stateMachine) : base(stateMachine) {}
public override void Enter()
{
stateMachine.Animator.CrossFadeInFixedTime(ImpactHash, stateMachine.CrossFadeDuration);
stateMachine.ForceReceiver.OnForceCompleted += HandleOnForceCompleted;
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
}
public override void Exit()
{
stateMachine.ForceReceiver.OnForceCompleted -= HandleOnForceCompleted;
}
private void HandleOnForceCompleted()
{
stateMachine.SwitchState(new EnemyIdleState(stateMachine));
}
}
}
and my āPlayerImpactState.csā (ANOTHER SPOILER):
using UnityEngine;
namespace RPG.States.Player {
public class PlayerImpactState : PlayerBaseState
{
private readonly int ImpactHash = Animator.StringToHash("Impact");
public PlayerImpactState(PlayerStateMachine stateMachine) : base(stateMachine) {}
public override void Enter()
{
stateMachine.Animator.CrossFadeInFixedTime(ImpactHash, stateMachine.CrossFadeDuration);
stateMachine.ForceReceiver.OnForceCompleted += HandleOnForceCompleted;
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
}
public override void Exit()
{
stateMachine.ForceReceiver.OnForceCompleted -= HandleOnForceCompleted;
}
private void HandleOnForceCompleted()
{
SetLocomotionState();
}
}
}
Placing debugs around seems to work, butā¦ they both still freeze. I went through the tutorial twice so far, I still canāt find where I went wrong (apart from placing āHandleForceAppliedā in the StateMachine script (because the āStart()ā function needs that), instead of the āImpactStateā scriptsā¦
and I also have to mention that if we donāt give the āOnForceAppliedā event in āForceReceiver.csā a type of Vector3, we will get errors, so this is how itās written (since the force type using it in āAddForceā is of type Vector3):
public event System.Action <Vector3> OnForceApplied;
without doing that, āInvokeā wonāt take in the force Input (the stuff bixarrio and you teach meā¦ )
It sounds like OnForceCompleted isnāt getting calledā¦
Letās take a look at your ForceReceiver.cs scriptā¦
using UnityEngine;
namespace RPG.Movement
{
public class ForceReceiver : MonoBehaviour
{
[SerializeField] private float drag = 0.3f;
[SerializeField] private float minimumImpactVelocity = 0.1f;
private CharacterController controller;
private UnityEngine.AI.NavMeshAgent agent;
public event System.Action <Vector3> OnForceApplied;
public event System.Action OnForceCompleted;
bool forceActive;
private void Awake()
{
controller = GetComponent<CharacterController>();
agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
}
private float verticalVelocity;
private Vector3 impact;
private Vector3 dampingVelocity;
public Vector3 Movement => impact + Vector3.up * verticalVelocity;
private void Update()
{
if (verticalVelocity < 0f && controller.isGrounded)
{
verticalVelocity = Physics.gravity.y * Time.deltaTime;
}
else
{
verticalVelocity += Physics.gravity.y * Time.deltaTime;
}
impact = Vector3.SmoothDamp(impact, Vector3.zero, ref dampingVelocity, drag);
// if the squared magnitude of the impact is below the 'minimumImpactVelocity',
// reset the impact and enable the agent (i.e: he took the impact, now get back to normal)
if (forceActive)
{
if (impact.sqrMagnitude < minimumImpactVelocity)
{
impact = Vector3.zero;
OnForceCompleted?.Invoke();
forceActive = false;
if (agent) agent.enabled = false;
}
}
}
public void AddForce(Vector3 force, bool triggerKnockbackEvent = false)
{
impact += force;
if (agent) agent.enabled = false;
if (triggerKnockbackEvent) OnForceApplied?.Invoke(force);
}
}
}
public void AddForce(Vector3 force, bool triggerKnockbackEvent = false)
{
impact += force;
if (agent) agent.enabled = false;
if(triggerKnockbackEvent) OnForceApplied?.Invoke(force);
forceActive = true;
}
We need to know f the force is active so we only invoke that OnForceCompleted once. Without it, the force never depletes and of course OnForceCompleted never invokes.
I have no idea how I missed that, but itās fixed (for now, still testing it). Thank you again Brian for saving me
By the way, considering the current state of the project, suppose I want to open it from another project name, computer or something else, what do I need to check for to get it to work? I just gave that a go (because I wanted to test something else), but that did not go as expectedā¦ I canāt even get my controllers to work when the game runs for some reason (not on my main project, but on a copy I tried making out of it)
I imported all the necessary libraries for that (otherwise it wonāt run)
You could zip up the project folder (but remove the Library, obj and Temp folders from the zip) and unzip it in a new directory. (It should be that simple). Then you just add the project from disk in the Unity Hub.
Using source control, itās even easier, you just clone the project using your git client, then add the project from disk in the Unity Hub.
SOOā¦ Go to the unity project location, delete the temporary, library and object files and then unzip it wherever I want to take itā¦ Got it!
Quick question by the way, for the randomization part of the script, when assigning āforceAmountā, did you mean āforce.sqrMagnitudeā on the Right Hand Side? Placing āforceAmountā gives errors (for obvious reasonsā¦)
Apart from that, the randomization isnāt working against the player, only the enemyā¦ Iām guessing it has to do with the mathematical formula, Iām still trying to understand it
- ZIP the project
- Remove the Library, obj, and temp folders from the zip
- Go to a new directory
- Unzip the project in that new directory
Yes, I think I might have typed the changes on that one in by hand rather than pasting from the repo.
welp, will go investigate the randomizer a bit and see why my enemy canāt knock me back
Not sure what went wrong, but my player literally never goes into impact state, but the enemy does so 100% of the timeā¦ Any idea what went wrong?
Letās see your Start() and HandleImpact in the PlayerStateMachineā¦
void Start()
{
MainCameraTransform = Camera.main.transform;
// The following check ensures that if we kill an enemy, save the game, quit and then return later, he is indeed dead
// (the reason it's here is because 'RestoreState()' happens between 'Awake()' and 'Start()', so to counter for the delay, we do it in start too)
if (Health.IsDead()) SwitchState(new PlayerDeathState(this));
else SwitchState(new PlayerFreeLookState(this));
Health.onDie.AddListener(() => {
SwitchState(new PlayerDeathState(this));
});
Health.onResurrection.AddListener(() => {
SwitchState(new PlayerFreeLookState(this));
});
ForceReceiver.OnForceApplied += HandleForceApplied;
}
private void HandleForceApplied(Vector3 force)
{
if (Health.IsDead()) return;
SwitchState(new PlayerImpactState(this));
}
I removed the randomizer in āHandleForceApplied()ā for the moment, to see what went wrongā¦
Seeā¦ youāre asking why it didnāt randomize, and the two things I wanted to see were if the method was subscribed to and what your randomize code looked like.
The code I provided was merely an example anyways.
lol ironically enough, even without the randomizer my player was not going into impact state for some reasonā¦
Anyway, here is my tuned attempt with the randomizer, for both the player and the enemy state machine:
PlayerStateMachine:
private void HandleForceApplied(Vector3 force)
{
if (Health.IsDead()) return;
float forceAmount = Random.Range(0f, force.sqrMagnitude);
if (forceAmount > Random.Range(0f, SkillStore.GetSkillLevel(Skill.Attack))) // I created a getter for the SkillStore...
{
SwitchState(new PlayerImpactState(this));
}
}
EnemyStateMachine:
private void HandleForceApplied(Vector3 force)
{
if (Health.IsDead()) return;
float forceAmount = Random.Range(0f, force.sqrMagnitude);
if (forceAmount > Random.Range(0f, BaseStats.GetLevel())) {
SwitchState(new EnemyImpactState(this));
}
}
Whatās concerning me though, is that the impact state never gets entered for the player even without a randomizer, albeit the code is asking it to do soā¦
Edit: Through code debugging, the player enters the Impact state, but the animation is not playing for the player for some reasonā¦ I checked the hash, all seems wellā¦
Edit 2: Entering and Exiting the Impact state work perfectly fineā¦ now Iām going nuts about why in the world is the animation not playing!
Edit 3: LOOOOOOOOOOOOOOOOL I had ZERO Hit force applied to my first attack with the 1H-Sword, NO WONDER IT WASNāT WORKING!