Как я могу вращать камеру вокруг группы объектов, а не только одного? - PullRequest
0 голосов
/ 01 июня 2018

Камера является ребенком только одного солдата, а также целью является этот солдат.

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);
    }


}

Но теперь я хочу сделать две вещи.Чтобы камера вращалась вокруг всего солдата, а не только конкретного.А также заставить камеру медленно останавливаться, когда она смотрит на солдат.Теперь при запуске игры камера остается позади.

Использование флага 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>
    }
}

Затем я попытался добавить переменную замедленного флага 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?

ОБНОВЛЕНИЕ 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 голосов
/ 01 июня 2018

Чтобы вращаться вокруг всех солдат:

  1. Получить центр всех солдат (сложить мировое положение всех солдат и разделить на N количество солдат)
  2. Получите максимальное расстояние солдат от центра
  3. Поверните камеру вокруг центра и убедитесь, что она больше максимального расстояния от центра

Для замедления камерывниз перед лицом солдат:

  1. Среднее значение вектора 1015 * всех солдат.Мы называем этот вектор F.Это справедливо, поскольку все ваши солдаты, как правило, будут ориентированы в одном и том же общем направлении, чтобы этот запрос даже имел смысл.
  2. Рассчитайте направление D, которое является направлением от центра солдата к камере.Это легко: D = camera.transform.position - soldiersCenter
  3. Наконец, найдите острый угол между D и F, используя Vector3.Angle().Если этот угол меньше определенного порога, уменьшите moveSpeed камеры.

Фактический код легко написать, но я позволю вам попрактиковаться.Дайте мне знать, если вам нужна помощь

0 голосов
/ 01 июня 2018

Судя по звукам, кажется, что он уже способен вращаться вокруг одного солдата, так что делайте больше, чем один, просто беря среднее их местоположения.

Псевдокод:

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 += Vector3 или Vector3 / int, но если это так, просто создайте свойсвои собственные методы, если вы делаете это вручную (добавление vectorA.x + vectorB.x, vectorA.x / num и т. д.

Если сделать остановку камеры, когда она находится впереди, это немного сложнее. Возможно, вы захотите сделать некоторые проверкисначала убедитесь, что все они имеют одинаковое вращение, а затем проверьте каждый Update, будет ли взгляд на вращение камеры указывать на одного из солдат.

Но, если вы хотите, чтобы он замедлилсязатем, вместо того, чтобы проверить, может ли lookAtRotation указывать на солдата, проверьте, может ли он указать на offset поворота камеры, например:

Псевдокод:

lookRotation(transform.Rotation + offset)   // Use something like this to find Soldiers[0]

Затем, если он найдет его, вы можете использовать Lerp на вашей скорости, чтобы спрыгнуть назад до скорости 0.

Вам также придется поддерживатьList<Soldier> или Soldier[] как-то.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...