在这个脚本中,我使用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等)绝对不会发生任何事情:这是我的问题......对不起,我的英语不好,我是法国人;)
1条答案
按热度按时间6rqinv9w1#
使用这样的协程会把你的代码搞得一团糟,因为两个协程几乎可以同时运行,例如:
ToggleAimOn()
第一次执行时按下F5,但在它完成之前,您可以再次按下F5并调用ToggleAimOff()
,由于协程是异步的,这意味着它们可以同时运行,因此将创建真实的混乱的行为你可以尝试在
aim
旁边设置另一个标志来检查一个协程是否像这样运行: