在玩家对象周围以平滑的圆圈移动游戏对象
Moving gameobject in a smooth circle around the player object
我使用的是 unity 5.1.2,如果有区别的话。
我有一个游戏对象盾牌,我想围绕玩家移动一圈。我让它工作到一定程度,盾牌对输入反应良好但没有动画,因为它只是传送到新位置而不是在一个圆圈中平滑旋转。该游戏是 2D 自上而下的游戏,因此只能在 x/y 平面上工作。尝试过使用 lerp 和 slerp 但没有得到任何乐趣
非常感谢您帮助解决这个问题!
这是我目前的情况:
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
float distance = 0.8f; // distance from player so it doesn't clip
Vector3 direction = Vector3.up;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float angle = Mathf.Atan2 (Input.GetAxisRaw("rightH"), Input.GetAxisRaw("rightV"))* Mathf.Rad2Deg;
if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
{
direction = new Vector3(Input.GetAxis("rightH"),Input.GetAxis("rightV"), 0.0f ) ;
}
Ray ray = new Ray(target.position, direction);
transform.position = ray.GetPoint(distance);
if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1);
}
}
}
试试这个。由于对 Input.GetAxis("...")
的方法调用如此之多,您真的希望在开始时只调用一次并将其缓存到变量中以加快处理速度。此外,您实际上不需要检查 if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
两次,所以我将所有内容都放入其中一项检查中。我添加了一个 Time.smoothDeltaTime
的乘法,希望能为您解决问题
float h = Input.GetAxis("rightH");
float v = Input.GetAxis("rightV");
float angle = Mathf.Atan2(h, v) * Mathf.Rad2Deg;
if(h != 0f || v != 0f)
{
float step = Time.smoothDeltatime * speed;
direction = Vector3.RotateTowards(transform.forward, new Vector2(h, v).normalized, step, 0.0F);
Ray2D ray = new Ray2D(target.position, direction);
transform.position = ray.GetPoint(distance);
transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
}
经过大量搜索和一些帮助,我终于解决了问题,谢谢大家:) 这是我想出的解决方案
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
float distance = 0.8f; // distance from player so it doesn't clip
Vector3 direction = Vector3.up;
public float circSpeed = 0.1f; // Speed Shield moves around ship
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float rh = Input.GetAxisRaw("rightH");
float rv = Input.GetAxisRaw("rightV");
if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
{
Vector3 targetDir = new Vector3(rh, rv, 0.0f);
direction = Vector3.Slerp(transform.position-target.position, targetDir, circSpeed);
}
Ray ray = new Ray(target.position, direction); // cast ray in direction of point on circle shield is to go
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the radius
float angleY = transform.position.y - target.position.y;
float angleX = -(transform.position.x - target.position.x);
float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle
if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player, will need revisiting on animating shield properly
}
}
}
我使用的是 unity 5.1.2,如果有区别的话。
我有一个游戏对象盾牌,我想围绕玩家移动一圈。我让它工作到一定程度,盾牌对输入反应良好但没有动画,因为它只是传送到新位置而不是在一个圆圈中平滑旋转。该游戏是 2D 自上而下的游戏,因此只能在 x/y 平面上工作。尝试过使用 lerp 和 slerp 但没有得到任何乐趣
非常感谢您帮助解决这个问题!
这是我目前的情况:
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
float distance = 0.8f; // distance from player so it doesn't clip
Vector3 direction = Vector3.up;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float angle = Mathf.Atan2 (Input.GetAxisRaw("rightH"), Input.GetAxisRaw("rightV"))* Mathf.Rad2Deg;
if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
{
direction = new Vector3(Input.GetAxis("rightH"),Input.GetAxis("rightV"), 0.0f ) ;
}
Ray ray = new Ray(target.position, direction);
transform.position = ray.GetPoint(distance);
if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1);
}
}
}
试试这个。由于对 Input.GetAxis("...")
的方法调用如此之多,您真的希望在开始时只调用一次并将其缓存到变量中以加快处理速度。此外,您实际上不需要检查 if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
两次,所以我将所有内容都放入其中一项检查中。我添加了一个 Time.smoothDeltaTime
的乘法,希望能为您解决问题
float h = Input.GetAxis("rightH");
float v = Input.GetAxis("rightV");
float angle = Mathf.Atan2(h, v) * Mathf.Rad2Deg;
if(h != 0f || v != 0f)
{
float step = Time.smoothDeltatime * speed;
direction = Vector3.RotateTowards(transform.forward, new Vector2(h, v).normalized, step, 0.0F);
Ray2D ray = new Ray2D(target.position, direction);
transform.position = ray.GetPoint(distance);
transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
}
经过大量搜索和一些帮助,我终于解决了问题,谢谢大家:) 这是我想出的解决方案
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
float distance = 0.8f; // distance from player so it doesn't clip
Vector3 direction = Vector3.up;
public float circSpeed = 0.1f; // Speed Shield moves around ship
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float rh = Input.GetAxisRaw("rightH");
float rv = Input.GetAxisRaw("rightV");
if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
{
Vector3 targetDir = new Vector3(rh, rv, 0.0f);
direction = Vector3.Slerp(transform.position-target.position, targetDir, circSpeed);
}
Ray ray = new Ray(target.position, direction); // cast ray in direction of point on circle shield is to go
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the radius
float angleY = transform.position.y - target.position.y;
float angleX = -(transform.position.x - target.position.x);
float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle
if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player, will need revisiting on animating shield properly
}
}
}