简体   繁体   English

unity旋转Object改变方向

[英]Unity Rotate Object to Change Direction

I have a fish which is swimming across the screen.我有一条鱼在屏幕上游来游去。 When it gets within 10% of the edge of the screen, I want it to turn begin turning around until it has completely reversed and is now swimming in the opposite direction.当它到达屏幕边缘的 10% 以内时,我希望它开始转身,直到它完全反转并且现在朝相反的方向游动。 This should be more gradual like a fish would swim.这应该更渐进,就像鱼会游泳一样。 I don't want it to rotate on its own axis.我不希望它在自己的轴上旋转。

I'm not having any luck getting it to turn around.我没有任何运气让它转身。 It only turns partially.它只是部分转动。

Update Here's the fish更新这是鱼在此处输入图像描述

public class FishSwim : MonoBehaviour
{
    public enum Direction { LeftToRight, RightToLeft };

    public Direction moveDirection;
    [SerializeField]
    private float speedMin = 0.5f;
    [SerializeField]
    private float speedMax = 1f;

    [SerializeField]
    private bool useOnlySpeedMax = false;
    private float speed;

    [HideInInspector]
    public float removeBeyond;

    private void Start()
    {
        var dist = (transform.position - Camera.main.transform.position).z;
        if (moveDirection == Direction.RightToLeft)
            removeBeyond = Camera.main.ViewportToWorldPoint(new Vector3(1, 0, dist)).x;
        else
            removeBeyond = Camera.main.ViewportToWorldPoint(new Vector3(1, 0, dist)).x + FindObjectOfType<SkinnedMeshRenderer>().bounds.size.x;
    }

    private void OnEnable()
    {
        speed = Random.Range(speedMin, speedMax);
        if (useOnlySpeedMax)
        {
            speed = speedMax;
        }
        if (moveDirection == Direction.RightToLeft)
        {
            speed = -speed;
        }
    }

    // Update is called once per frame
    void Update()
    {
        float realSpeed = speed * Time.deltaTime;
        transform.position += Vector3.right * realSpeed;
        if (moveDirection == Direction.RightToLeft && transform.position.x < -Mathf.Abs(removeBeyond))
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(Vector3.right), Time.deltaTime * 40f);
            moveDirection = Direction.LeftToRight;
        }
        else if (moveDirection == Direction.LeftToRight && transform.position.x > Mathf.Abs(removeBeyond))
        {
            
        }
    }
}

I would use Coroutines to do this.我会使用协程来做到这一点。 Explanation in comments:评论中的解释:

bool isTurning = false;
[SerializeField] float turnPeriod = 0.5f; // how long it takes to turn, smaller=faster

private void OnEnable()
{
    speed = Random.Range(speedMin, speedMax);
    if (useOnlySpeedMax)
    {
        speed = speedMax;
    }
    // Get rid of negative speed
}

void Update()
{
    float realDistance = speed * Time.deltaTime;
    transform.position += transform.right * realDistance;

    // Surely there is a better way than calculating 
    // Mathf.Abs(removeBeyond) every frame... but that is off-topic
    if (!isTurning && ( 
        (moveDirection == Direction.RightToLeft 
            && transform.position.x < -Mathf.Abs(removeBeyond) 
        ) || (moveDirection == Direction.LeftToRight
            && transform.position.x > Mathf.Abs(removeBeyond) 
    ) ) )
    {
        // If we aren't already turning and we should be, start turning:
        StartCoroutine(Turn());
    }
}

IEnumerator Turn()
{
    isTurning = true;
    Vector3 startForward = transform.forward;

    // find end speed and direction
    Direction endDirection = moveDirection == Direction.RightToLeft ?
            Direction.LeftToRight:Direction.RightToLeft; 

    // keep track of how much of our turning time has elapsed
    float elapsedTimePortion = Time.deltaTime/turnPeriod;

    // turn until you've spent enough time turning
    while (elapsedTimePortion < 1f)
    {
        // by whatever portion we've spent time turning, turn starting forward
        // 180 degrees around up axis
        float angle = 180f * elapsedTimePortion;
        Vector3 newForward = Quaternion.AngleAxis(angle, Vector3.up) * startForward;
        transform.rotation = Quaternion.LookRotation(newForward);
        yield return null;
 
        // next frame - update how long we've been turning
        float newElapsedTimePortion = elapsedTimePortion + Time.deltaTime/turnPeriod;

        if (newElapsedTimePortion >= 0.5f && elapsedTimePortion < 0.5f)
        {
            // If we've just passed 50% of the turn, 
            // make fish move opposite direction
            moveDirection = endDirection; 
        }
        elapsedTimePortion = newElapsedTimePortion;
    } 

    // we're done turning, just set the rotation to the end rotation.
    isTurning = false;
    transform.rotation = Quaternion.LookRotation(-startForward);

    // Does removeBeyond need to be updated here? There are a few lines in Start()
    // which would suggest that.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM