unity3d Input.GetKeyDown调用一个协程来放入第一人称,但它阻止了角色的移动

bwleehnv  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(154)

在这个脚本中,我使用Input调用了一个协程;这个协同程序允许如果我们按下F5键,将我们在第三人称模式下看到的角色视图更改为第一人称模式,如果我们再次按下F5键,它将替换视图.只是,通过使用input.getKey而不是input.getKeyDown,协同程序将读取几次,这将给出一个丑陋的结果.但是当我使用Input.getKeyDown时,我在第一人称模式下(基本视角是第三人称),角色的移动被阻止:我无法前进、后退、跳转等...脚本中的错误?
如果您想在unity上进行测试,只需下载此链接https://github.com/TUTOUNITYFR/unitypackages-jeu-survie-2022-tufr/blob/main/Episode01/personnage-et-environnement.unitypackage上的文件,然后在AimBehaviourBasic脚本中,将所有代码替换为:
`

using UnityEngine;
using System.Collections;

// AimBehaviour inherits from GenericBehaviour. This class corresponds to aim and strafe behaviour.
public class AimBehaviourBasic : GenericBehaviour
{

    public Texture2D crosshair;                                           // Crosshair texture.
    public float aimTurnSmoothing = 0.15f;                                // Speed of turn response when aiming to match camera facing.
    public Vector3 aimPivotOffset = new Vector3(0.5f, 1.2f,  0f);         // Offset to repoint the camera when aiming.
    public Vector3 aimCamOffset   = new Vector3(0f, 0.4f, -0.7f);         // Offset to relocate the camera when aiming.

    private int aimBool;                                                  // Animator variable related to aiming.
    public bool aim;                                                      // Boolean to determine whether or not the player is aiming.

    // Start is always called after any Awake functions.
    void Start ()
    {
        // Set up the references.
        aimBool = Animator.StringToHash("Aim");
    }

    // Update is used to set features regardless the active behaviour.
    void Update ()
    {
        // Activate/deactivate aim by input.
        if (Input.GetKeyDown (KeyCode.F5) && !aim)
        {
            StartCoroutine(ToggleAimOn());
        }
        else 
        if (Input.GetKeyDown (KeyCode.F5) && aim)
        {           
            StartCoroutine(ToggleAimOff());         
        }
    }

    // Co-rountine to start aiming mode with delay.
    private IEnumerator ToggleAimOn()
    {
        yield return new WaitForSeconds(0.05f);
        // Aiming is not possible.
        if (behaviourManager.GetTempLockStatus(this.behaviourCode) || behaviourManager.IsOverriding(this))
            yield return false;
        // Start aiming.
        else
        {
            aim = true;
            int signal = 1;
            yield return new WaitForSeconds(0.1f);
            aimCamOffset.x = Mathf.Abs(aimCamOffset.x) * signal;
            aimPivotOffset.x = Mathf.Abs(aimPivotOffset.x) * signal;
            yield return new WaitForSeconds(0.1f);
            behaviourManager.GetAnim.SetFloat(speedFloat, 0);
            // This state overrides the active one.
            behaviourManager.OverrideWithBehaviour(this);
        }
    }

    // Co-rountine to end aiming mode with delay.
    private IEnumerator ToggleAimOff()
    {
        
        aim = false;
        yield return new WaitForSeconds(0.3f);
        behaviourManager.GetCamScript.ResetTargetOffsets();
        behaviourManager.GetCamScript.ResetMaxVerticalAngle();
        yield return new WaitForSeconds(0.05f);
        behaviourManager.RevokeOverridingBehaviour(this);
    }

    // LocalFixedUpdate overrides the virtual function of the base class.
    public override void LocalFixedUpdate()
    {
        // Set camera position and orientation to the aim mode parameters.
        if(aim)
        {
            behaviourManager.GetCamScript.SetTargetOffsets (aimPivotOffset, aimCamOffset);
        }
    }

    // LocalLateUpdate: manager is called here to set player rotation after camera rotates, avoiding flickering.
    public override void LocalLateUpdate()
    {
        AimManagement();
    }

    // Handle aim parameters when aiming is active.
    void AimManagement()
    {
        // Deal with the player orientation when aiming.
        Rotating();
    }

    // Rotate the player to match correct orientation, according to camera.
    void Rotating()
    {
        

        // Always rotates the player according to the camera horizontal rotation in aim mode.
        Quaternion targetRotation =  Quaternion.Euler(0, behaviourManager.GetCamScript.GetH, 0);

        float minSpeed = Quaternion.Angle(transform.rotation, targetRotation) * aimTurnSmoothing;

        // Rotate entire player to face camera.
        
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, minSpeed * Time.deltaTime);

    }

    // Draw the crosshair when aiming.
    void OnGUI () 
    {
        if (crosshair)
        {
            float mag = behaviourManager.GetCamScript.GetCurrentPivotMagnitude(aimPivotOffset);
                GUI.DrawTexture(new Rect(Screen.width / 2 - (crosshair.width * 0.5f),
                                         Screen.height / 2 - (crosshair.height * 0.5f),
                                         crosshair.width, crosshair.height), crosshair);
        }
    }
}

`
现在可以测试了,按播放键然后按F5:摄像机将改变位置,但如果你试图移动(les touches:Z、Q、S、D、escape或arrowUp、arrowDown等)绝对不会发生任何事情:这是我的问题......对不起,我的英语不好,我是法国人;)

6rqinv9w

6rqinv9w1#

使用这样的协程会把你的代码搞得一团糟,因为两个协程几乎可以同时运行,例如:

  • 如果您在ToggleAimOn()第一次执行时按下F5,但在它完成之前,您可以再次按下F5并调用ToggleAimOff(),由于协程是异步的,这意味着它们可以同时运行,因此将创建真实的混乱的行为

你可以尝试在aim旁边设置另一个标志来检查一个协程是否像这样运行:

private bool IsCoroutineActive = false;
void Update ()
{
    // Activate/deactivate aim by input.
    if (Input.GetKeyDown (KeyCode.F5) && !IsCoroutineActive  && !aim)
    {
        StartCoroutine(ToggleAimOn());
    }
    else 
    if (Input.GetKeyDown (KeyCode.F5) && !IsCoroutineActive && aim)
    {           
        StartCoroutine(ToggleAimOff());         
    }
}

// Co-rountine to start aiming mode with delay.
private IEnumerator ToggleAimOn()
{
    IsCoroutineActive = true;
    yield return new WaitForSeconds(0.05f);
    // Aiming is not possible.
    if (behaviourManager.GetTempLockStatus(this.behaviourCode) || behaviourManager.IsOverriding(this))
    {
        IsCoroutineActive = false;
        yield return false;
    }
    // Start aiming.
    else
    {
        aim = true;
        int signal = 1;
        yield return new WaitForSeconds(0.1f);
        aimCamOffset.x = Mathf.Abs(aimCamOffset.x) * signal;
        aimPivotOffset.x = Mathf.Abs(aimPivotOffset.x) * signal;
        yield return new WaitForSeconds(0.1f);
        behaviourManager.GetAnim.SetFloat(speedFloat, 0);
        // This state overrides the active one.
        behaviourManager.OverrideWithBehaviour(this);
    }

    IsCoroutineActive = false;
}

// Co-rountine to end aiming mode with delay.
private IEnumerator ToggleAimOff()
{
    IsCoroutineActive = true;
    aim = false;
    yield return new WaitForSeconds(0.3f);
    behaviourManager.GetCamScript.ResetTargetOffsets();
    behaviourManager.GetCamScript.ResetMaxVerticalAngle();
    yield return new WaitForSeconds(0.05f);
    behaviourManager.RevokeOverridingBehaviour(this);
    IsCoroutineActive = false;
}

相关问题