Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
78 views
Welcome To Ask or Share your Answers For Others

1 Answer

You're calling Dodge on a prefab instead of the scene instance of that prefab which is running CreatureMovement.FixedUpdate.

I believe you can verify this by placing this code in Dodge (Source: Max-Pixel):

if (gameObject.scene.name == null) Debug.Log("It's a prefab!");

You need to change your input processing to call Dodge on the instance in the scene instead of a prefab.

You can do that by dragging the instance in the scene into the button onclick event, then selecting Dodge. Or, if you are spawning the object dynamically, you could, in Start, find a reference to the button, and add Dodge to its onClick listeners:

private void Start()
{
    movement.Rigidbody = rigidbody;  
    // something along the lines of this...
    Button buttonRef = GameObject.Find("ButtonName").GetComponent<Button>();

    buttonRef.onClick.AddListener(Dodge);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...