The issue is with the boolean isDodging
. It is set to true in the Dodge()
method. That should trigger an if statement in the Movement()
method (called in FixedUpdate()
) but that block is always skipped over. I'm attaching all of the class' code, because there must be something I'm missing here:
using UnityEngine;
public class MovementController
{
/* COMPONENTS */
public Rigidbody2D Rigidbody { private get; set; }
/* VARIABLES */
private bool isDodging = false;
private Vector2 dodgeDirection = Vector2.right;
private float dodgeDuration = 1f;
private float dodgeSpeed = 20f;
private float timer = 0f;
/* METHODS */
// Called in fixed update (since it's dealing with physics)
public void Movement(Vector2 currentPosition, Vector2 velocity)
{
Debug.Log("In movement: " + isDodging);
if (isDodging)
{
Debug.Log("Dodge 3");
Move(currentPosition, dodgeDirection * dodgeSpeed);
timer += Time.fixedDeltaTime;
if (timer >= dodgeDuration)
{
Debug.Log("Stopped dodging " + Time.fixedTime);
isDodging = false;
}
}
else
{
Move(currentPosition, velocity);
}
}
private void Move(Vector2 currentPosition, Vector2 velocity)
{
if (Rigidbody == null)
{
Debug.LogWarning("No rigidbody to move!");
return;
}
Rigidbody.MovePosition(currentPosition + (velocity * Time.fixedDeltaTime));
}
// Must be called while Movement is being called
public void Dodge(Vector2 direction, float maxSpeed, float speedMultiplier = 2f, float duration = 1f)
{
if (direction == Vector2.zero) { return; }
Debug.Log("Dodge 1 " + isDodging);
dodgeDirection = direction;
dodgeDuration = duration;
dodgeSpeed = maxSpeed * speedMultiplier;
isDodging = true;
Debug.Log("Dodge 2" + isDodging + Time.fixedTime);
timer = 0f;
}
}
The thing is, the "In movement: " log always shows isDodging as false
, and the if block under it never runs. Meanwhile, "Dodge 2" will show true
(as isDodging
is changed right above it). And the weirdest: "Dodge 1" shows false
the first time Dodge()
is called, but true
everytime its called after that - as if isDodging
was changed to true in the class scope, and Movement()
doesn't recognize that for some reason.
Both this functions are called in a separate MonoBehaviour:
public class CreatureMovement : MonoBehaviour
{
[Header("Movement")]
[SerializeField] protected Vector2Reference moveDirection;
[SerializeField] protected FloatReference maxSpeed;
[Header("Dodge")]
[SerializeField] private FloatReference dodgeDuration;
[SerializeField] private FloatReference dodgeSpeedMultiplier;
[Header("References")]
[SerializeField] private new Rigidbody2D rigidbody;
private readonly MovementController movement = new MovementController();
public float MaxSpeed { get => maxSpeed; }
private float speed;
private float Speed { get => speed; set => speed = Mathf.Clamp(value, 0, maxSpeed); }
public virtual Vector2 Velocity
{
get => moveDirection.Value * Speed;
set
{
moveDirection.SetValue(value.normalized);
Speed = value.magnitude;
}
}
private void Start() => movement.Rigidbody = rigidbody;
private void FixedUpdate() => movement.Movement(transform.position, Velocity);
public void Dodge() => movement.Dodge(moveDirection, maxSpeed, dodgeSpeedMultiplier, dodgeDuration);
}
Where Dodge()
is called from player input.
Except for dodging, movement is ocurring exactly as expected. The problem probably isn't in the Move()
method, as it doesn't have isDodging
in it.
I have absolutey no idea why this is happening, the code seems so simple to me, but it just isn't working. Please help out with this.
question from:https://stackoverflow.com/questions/66054556/method-ignores-class-scope-variable-value-change