【发布时间】:2020-11-07 10:41:55
【问题描述】:
我正在 Unity 中制作足球模拟游戏,并且我有一个基本的 Player_Agent 类来处理非智能动作,如跑步、跳跃等。我有一个协程 Dive(Vector2 a_direction),代理应该旋转以面对 a_direction然后向前移动,直到它的高度回到它的起始高度。但是,每当我执行这个协程时,它都会旋转到面向 a_direction 的方向,然后完全退出 Dive 协程。
我发现的每篇文章都建议按照我的实现方式进行操作,使用yield return StartCoroutine(TurnTo(Vector2 a_direction));,如果我将其更改为StartCoroutine(TurnTo(a_direction)); yield return null;,那么它将同时执行两个例程,这不是预期的结果。我用 StartRoutine() 和没有它都试过了,有点迷路了。我没有尝试正确实现这一点,还是只是语法错误?
MVP:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Agent : MonoBehaviour
{
// Dynamic Variables
//--------------------------------------------------
public float w_speed;
public float w_height;
public Vector2 w_direction;
// Member Variables
//--------------------------------------------------
/// <summary></summary>
public float m_speed; // Set to 5 in unity editor
public float m_acceleration; // Set to 1 in unity editor
public float m_vertical; // Set to 1 in unity editor
public float m_height; // Set to 2 in unity editor
// --------------------------------------------------
// GAMEPLAY METHODS
// --------------------------------------------------
#region Gameplay Methods
/// <summary>
/// Turns the agent towards the target direction
/// </summary>
/// <param name="a_direction">A unit vector representing the desired result for w_direction </param>
/// <returns>A coroutine of the agent turning </returns>
public IEnumerator TurnTo(Vector2 a_direction)
{
// Initialize helper variables
Vector2 t_direction_0 = w_direction;
float t_time = Time.deltaTime;
float t_angle = Mathf.Atan2(a_direction.y, a_direction.x) * Mathf.Rad2Deg;
Quaternion t_quat_0 = transform.rotation;
Quaternion t_quat_1 = Quaternion.AngleAxis(t_angle, Vector3.forward);
// While not facing the correct direction
while (w_direction != a_direction)
{
// Use slerp to dynamically rotate and change w_direction
Quaternion t_quat = Quaternion.Slerp(t_quat_0,t_quat_1,t_time);
transform.rotation = t_quat;
w_direction = (t_quat * t_direction_0).normalized;
yield return null;
// Update time elapsed
t_time += Time.deltaTime;
}
// Ensure that there is no error
w_direction = a_direction.normalized;
}
/// <summary>
/// Turns the agent towards the target direction
/// </summary>
/// <param name="a_angle">A float between 0 and 360 representing the turning angle </param>
/// <returns>A coroutine of the agent turning </returns>
public IEnumerator TurnTo(float a_angle)
{
// Initialize helper variables
Vector2 t_direction_0 = w_direction;
float t_time = Time.deltaTime;
Quaternion t_quat_0 = transform.rotation;
Quaternion t_quat_1 = t_quat_0 * Quaternion.AngleAxis(a_angle, Vector3.forward);
Debug.Log("Turning");
// While not facing the correct direction
while (transform.rotation != t_quat_1)
{
// Use slerp to dynamically rotate and change w_direction
Quaternion t_quat = Quaternion.Slerp(t_quat_0, t_quat_1, t_time);
transform.rotation = t_quat;
w_direction = (t_quat * t_direction_0).normalized;
yield return null;
// Update time elapsed
t_time += Time.deltaTime;
}
}
public IEnumerator Dive(Vector2 a_direction)
{
// Initialize helping variables
float t_height = m_height + m_vertical * Time.deltaTime;
float t_time = Time.deltaTime;
Vector2 t_position_0 = (Vector2)transform.position;
Vector2 t_position = new Vector2(t_position_0.x, t_position_0.y);
bool hasJumped = false;
Coroutine t_coroutine;
// If not facing a_direction
if (w_direction != a_direction)
{
// Turn towards a_direction
yield return StartCoroutine(TurnTo(a_direction));
}
// While the agent hasn't jumped and is stil in the air
while ((t_height - m_height) > 0.01f || hasJumped == false)
{
// Update w_height and position
w_height = t_height;
transform.position = t_position;
yield return null;
// Update t_time and t_height
t_time += Time.deltaTime;
t_height = m_height + 2.5f * m_vertical * 0.7071f * t_time - 4.9f * Mathf.Pow(t_time, 2);
t_position = t_position_0 + (m_vertical + w_speed) * t_time * a_direction;
Debug.Log(t_height);
// Flip hasJumped flag
if (!hasJumped) { hasJumped = true; }
}
// Reset w_height
w_height = m_height;
}
#endregion
}
注意:显然不是完成或完善的设置,但这是我在其他几个计划方法中出现的模式,我想确保在我这样做之前我正在实施它。
【问题讨论】: