如何围绕一组物体旋转相机而不仅仅是一个?

时间:2018-06-01 08:43:40

标签: c# unity3d

相机只是一名士兵的孩子,目标也是这名士兵。

Camera

脚本附在相机上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour
{

    public Transform target;
    public float speed = 0.1f;

    // Use this for initialization
    void Start ()
    {

    }

    // Update is called once per frame
    void Update ()
    {
        transform.RotateAround(target.transform.position, new Vector3(0, 1, 0), 100 * Time.deltaTime * speed);
    }


}

但现在我想做两件事。使相机围绕整个士兵而不仅仅是特定的一个旋转。并且当它面向士兵时,使相机慢慢停止。现在开始游戏后相机就落后了。

如果为true,则使用bool标志使摄像机围绕士兵旋转,直到面对他们然后停止旋转并继续与士兵一起移动。

如果未经检查,则假设相机在焊料周围旋转,则无法停止。

更新到目前为止我尝试的内容:

此代码将使其围绕所有士兵旋转,并且工作正常:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    public float speed = 0.1f;

    private List<GameObject> Soldiers = new List<GameObject>();

    // Use this for initialization
    void Start()
    {
        Soldiers.AddRange(GameObject.FindGameObjectsWithTag("Soldier"));
    }

    // Update is called once per frame
    void Update()
    {
        RotateAround();
    }

    private void RotateAround()
    {
        transform.RotateAround(GetAverageLocationOfSoliders(), new Vector3(0, 1, 0), 100 * Time.deltaTime * speed);
    }

    private Vector3 GetAverageLocationOfSoliders()
    {
        var total = new Vector3();

        foreach (var soldier in Soldiers)
            total += soldier.transform.position;

        return total / Soldiers.Count();    // Assuming Soldiers is List<Soldier>
    }
}

然后我尝试添加一个slowDown bool标志变量,但是我搞砸了它并且它根本不起作用。

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    public float speed = 0.1f;
    public bool slowDown = false;

    private List<Vector3> SoldiersPositions = new List<Vector3>();
    private List<Vector3> SoldiersFacingDirection = new List<Vector3>();

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void FixedUpdate()
    {
        RotateAround();
    }

    private void RotateAround()
    {
        var getSoldiers = GameObject.FindGameObjectsWithTag("Soldier");
        foreach (GameObject soldier in getSoldiers)
        {
            SoldiersPositions.Add(soldier.transform.position);
            SoldiersFacingDirection.Add(soldier.transform.forward);
        }

        var Center = GetAverageLocationOfSoliders();
        var FacingDirections = GetAverageFacingDirectionOfSoldiers();
        if (slowDown == true)
        {
            var D = transform.position - Center;
            var CamAngle = Vector3.Angle(D, FacingDirections);
            speed = speed - CamAngle;
        }

        transform.RotateAround(Center, new Vector3(0, 1, 0), 100 * Time.deltaTime * speed);
        SoldiersPositions = new List<Vector3>();
        SoldiersFacingDirection = new List<Vector3>();
    }

    private Vector3 GetAverageLocationOfSoliders()
    {
        var total = new Vector3();

        foreach (var soldier in SoldiersPositions)
            total += soldier;

        return total / SoldiersPositions.Count();    // Assuming Soldiers is List<Soldier>
    }

    private Vector3 GetAverageFacingDirectionOfSoldiers()
    {
        var total = new Vector3();

        foreach (var soldierfacingdir in SoldiersFacingDirection)
            total += soldierfacingdir;

        return total / SoldiersFacingDirection.Count();
    }
}
  1. 我不确定只有旋转的第一个代码示例是否与我编写它的方式相同。它工作但不确定这是否是一个很好的方法来执行代码?

  2. 在我看来,在第一个代码中,只有旋转相机有点摇晃或口吃,我的意思是相机在旋转时不能平滑移动。在编辑器的游戏视图中几乎很难看到,但你可以在我认为的场景视图中看到它。

  3. 我调用RotateAround()的原因;在更新中,士兵们正在不停地向前走。

  4. 我该怎么做slowDown部分?

  5. 更新2:

    现在这是完整的男女同校:

    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
    public class CameraMove : MonoBehaviour
    {
        [Header("Spin")]
        public bool spin = false;
        public Vector3 Direction;
        [Range(0, 300)]
        public float speed = 10f;
        public bool randomSpeed = false;
        public bool randomDirection = false;
        [Range(0f, 100f)]
        public float timeDirChange;
        public Vector3 defaultDirection;
    
        [Space(5)]
    
        [Header("Move in circles")]
        public bool moveInCircles = true;
        public GameObject rotateAroundTarget;
        public Vector3 axis;//by which axis it will rotate. x,y or z.
        public float rotationSpeed; //or the speed of rotation.
        public float upperLimit, lowerLimit, delay;// upperLimit & lowerLimit: heighest & lowest height;
        public bool randomHeight = false;
        public bool stopRotatingWhenFacing = false;
        private float height, prevHeight, time;//height:height it is trying to reach(randomly generated); prevHeight:stores last value of height;delay in radomness;
    
    
        [Space(5)]
    
        [Header("Follow objects")]
        public GameObject[] objectsToFollow;
        public bool randomFollow;
    
        private float nextRotationTime = 0f;
        private int counter = 0;
        private List<GameObject> Soldiers = new List<GameObject>();
    
        // Use this for initialization
        void Start()
        {
            Soldiers.AddRange(GameObject.FindGameObjectsWithTag("Soldier"));
        }
    
        private void Update()
        {
            if (randomSpeed)
            {
                speed = UnityEngine.Random.Range(0, 300);
            }
    
            if (spin)
            {
                if (randomDirection == false)
                {
                    nextRotationTime = 0;
                    timeDirChange = 0;
                    Direction = defaultDirection;
                }
                else
                {
                    if (Time.time > nextRotationTime)
                    {
                        nextRotationTime += timeDirChange;
                        RandomDirection();
                    }
                }
    
                transform.Rotate(Direction, speed * Time.deltaTime);
            }
            else
            {
                timeDirChange = 0;
                randomDirection = false;
                randomSpeed = false;
            }
    
            if (moveInCircles)
            {
                MoveInCircles();
            }
        }
    
        private void RandomDirection()
        {
            Direction = new Vector3(UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1));
            while (Direction == new Vector3(0, 0, 0))
            {
                counter++;
                Direction = new Vector3(UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1));
    
                if (counter == 2)
                {
                    Direction = new Vector3(1, 0, 0);
                    break;
                }
            }
    
            counter = 0;
        }
    
        private void MoveInCircles()
        {
            var F = GetAverageDirectionsOfSoliders();
            var D = transform.position - GetAverageLocationOfSoliders();
            var angle = Vector3.Angle(D, F);
    
            if (angle < 5f)
            {
                rotationSpeed -= 0.1f;
            }
    
            transform.RotateAround(GetAverageLocationOfSoliders(), axis, rotationSpeed);
            time += Time.deltaTime;
            //Sets value of 'height' randomly within 'upperLimit' & 'lowerLimit' after delay 
            if (time > delay)
            {
                prevHeight = height;
                if (randomHeight)
                {
                    height = UnityEngine.Random.Range(lowerLimit, upperLimit);
                }
                time = 0;
            }
    
            if (randomHeight == false)
            {
                height = transform.position.y;
            }
    
            if (randomHeight)
            {
                //Mathf.Lerp changes height from 'prevHeight' to 'height' gradually (smooth transition)  
                transform.position = new Vector3(transform.position.x, Mathf.Lerp(prevHeight, height, time), transform.position.z);
            }
            else
            {
                transform.position = new Vector3(transform.position.x, height, transform.position.z);
            }
        }
    
        private Vector3 GetAverageLocationOfSoliders()
        {
            var total = new Vector3();
    
            foreach (var soldier in Soldiers)
            {
                total += soldier.transform.position;
            }
    
            return total / Soldiers.Count();    // Assuming Soldiers is List<Soldier>
        }
    
        private Vector3 GetAverageDirectionsOfSoliders()
        {
            var totalf = new Vector3();
    
            foreach (var soldier in Soldiers)
            {
                totalf += soldier.transform.forward;
            }
    
            return totalf / Soldiers.Count();
        }
    }
    

    RotateAround部分工作正常:

    transform.RotateAround(GetAverageLocationOfSoliders(), axis, rotationSpeed);
    

    但减速部分不起作用。当相机对着士兵时,它并没有减速。

    这是我计算所有士兵的平均transform.forward矢量的方法:

    private Vector3 GetAverageDirectionsOfSoliders()
        {
            var totalf = new Vector3();
    
            foreach (var soldier in Soldiers)
            {
                totalf += soldier.transform.forward;
            }
    
            return totalf / Soldiers.Count();
        }
    

    然后在MoveInCircles方法中我做了:

    var F = GetAverageDirectionsOfSoliders();
            var D = transform.position - GetAverageLocationOfSoliders();
            var angle = Vector3.Angle(D, F);
    
            if (angle < 5f)
            {
                rotationSpeed -= 0.1f;
            }
    

    但它永远不会上线:

    rotationSpeed -= 0.1f;
    

2 个答案:

答案 0 :(得分:3)

围绕所有士兵旋转:

  1. 获得所有士兵的中心(总和所有士兵的世界位置并除以N士兵数量)
  2. 获得士兵离中心的最大距离
  3. 围绕中心旋转相机,并确保它距离中心的最大距离
  4. 面对士兵时,请将相机放慢速度。前:

    1. 平均所有士兵的transform.forward向量。我们称这个向量为F。这是公平的,因为你的所有士兵通常都面临着这个要求甚至有意义的相同方向。
    2. 计算方向D,这是士兵的方向。相机的中心。这很简单:D = camera.transform.position - soldiersCenter
    3. 最后,使用D找到FVector3.Angle()之间的锐角。如果此角度低于某个阈值,请减小相机的moveSpeed
    4. 实际代码很容易编写,但我会让你练习。如果您需要任何帮助,请告诉我

答案 1 :(得分:1)

从它的声音来看,似乎你已经能够围绕一个士兵进行环绕,所以不止一个,只需要取其位置的平均值。

伪码:

transform.RotateAround(GetAverageLocationOfSoliders(), ...);
...
private static Vector3 GetAverageLocationOfSoliders
{
    var total = new Vector3();

    foreach(var soldier in Soldiers)
        total += soldier.transform.position;

    return total / Soliders.Count();    // Assuming Soldiers is List<Soldier>
}

现在,Vector3可能没有像Vector3 += Vector3Vector3 / int这样的内容,但如果是这样,那么只需创建自己的方法就可以手动执行此操作(添加{{} 1}}和vectorA.x + vectorB.x等等。

当相机在前面停下来时,这有点棘手。您可能需要先进行一些检查以确保它们都具有相同的旋转,然后检查每个vectorA.x / num,如果相机的旋转外观指向其中一个士兵。

但是,如果你希望它减速,那么,不要检查Update是否可以指向士兵,而是检查它是否可以指向相机的某些lookAtRotation旋转,如:

伪代码:

offset

然后,如果找到一个,你可以使用你的速度lookRotation(transform.Rotation + offset) // Use something like this to find Soldiers[0] 来恢复速度为0.

您还必须以某种方式维护LerpList<Soldier>