@polyakovyevgeniy

Вращение камеры вокруг объекта свайпом в Unity3D?

Подскажите пожалуйста как можно сделать чтобы камера вращалась вокруг объекта пальцем просто по кругу и работала как прокрутка. То есть свайп сделал, и она сама еще немного вращается по инерции.

У меня есть сфера. Есть камера и куб. Камера является дочерним элементом к кубу. А сфера это тот объект в центре которого должен находиться куб и вращаться по ее оси. Я должен свайп по экрану сделать, и куб должен начать вращаться в ту или другую строну с инерцией. Есть примеры как можно это сделать?
  • Вопрос задан
  • 5204 просмотра
Решения вопроса 1
BasmanovDaniil
@BasmanovDaniil
Геймдизайнер-телепат
В моём тулките есть контроллер для камеры, которое делает то, что вы хотите, но на основе UI, чтобы было проще ограничивать распространение событий нажатий. Посмотреть на него в действии можете здесь. Если канвас не используете, то можете код из OnDrag перенести в какой-нибудь апдейт и дельту считать руками.

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace ProceduralToolkit.Examples
{
    /// <summary>
    /// Simple camera controller
    /// </summary>
    [RequireComponent(typeof (Image))]
    public class CameraRotator : UIBehaviour, IDragHandler
    {
        public Transform cameraTransform;
        public Transform target;
        [Header("Position")]
        public float distanceMin = 10;
        public float distanceMax = 30;
        public float yOffset = 0;
        public float scrollSensitivity = 1000;
        public float scrollSmoothing = 10;
        [Header("Rotation")]
        public float tiltMin = -85;
        public float tiltMax = 85;
        public float rotationSensitivity = 0.5f;
        public float rotationSpeed = 20;

        private float distance;
        private float scrollDistance;
        private float velocity;
        private float lookAngle;
        private float tiltAngle;
        private Quaternion rotation;

        protected override void Awake()
        {
            base.Awake();
            tiltAngle = (tiltMin + tiltMax)/2;
            distance = scrollDistance = (distanceMax + distanceMin)/2;

            if (cameraTransform == null || target == null) return;

            cameraTransform.rotation = rotation = Quaternion.Euler(tiltAngle, lookAngle, 0);
            cameraTransform.position = CalculateCameraPosition();
        }

        private void LateUpdate()
        {
            if (cameraTransform == null || target == null) return;

            if (cameraTransform.rotation != rotation)
            {
                cameraTransform.rotation = Quaternion.Lerp(cameraTransform.rotation, rotation,
                    Time.deltaTime*rotationSpeed);
            }

            float scroll = Input.GetAxis("Mouse ScrollWheel");
            if (scroll != 0)
            {
                scrollDistance -= scroll*Time.deltaTime*scrollSensitivity;
                scrollDistance = Mathf.Clamp(scrollDistance, distanceMin, distanceMax);
            }

            if (distance != scrollDistance)
            {
                distance = Mathf.SmoothDamp(distance, scrollDistance, ref velocity, Time.deltaTime*scrollSmoothing);
            }

            cameraTransform.position = CalculateCameraPosition();
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (cameraTransform == null || target == null) return;

            lookAngle += eventData.delta.x*rotationSensitivity;
            tiltAngle -= eventData.delta.y*rotationSensitivity;
            tiltAngle = Mathf.Clamp(tiltAngle, tiltMin, tiltMax);
            rotation = Quaternion.Euler(tiltAngle, lookAngle, 0);
        }

        private Vector3 CalculateCameraPosition()
        {
            return target.position + cameraTransform.rotation*(Vector3.back*distance) + Vector3.up*yOffset;
        }
    }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
MrMureno
@MrMureno Куратор тега Unity
VR for all
Очень надеюсь что про сваип в гугл вы тоже найдете, там вроде все просто.

А вот по инерции принцип подскажу.
По сути в таче(и в курсоре мышки) есть дельта https://docs.unity3d.com/ScriptReference/Touch-del...
По сути - на сколько сместилась за кадр (если на апдеите считываете)
Так вот можно просто дельту, можно за несколько кадров усредненную (как кому больше нравится) - запомнить.

Вот эта запомненная дельта и будет мерой инертности) И по сути вам нужно просто продолжать на апдеите применять такую жу дельту к вращению и потихоньку её уменьшать (банально в том же апдеите множить на что то меньшее и близкое к единице, какие нибудь 0,97)

Собственно множитель и будет мерой инертности)

//////////
	                    Vector2 position = UnifiedInput.position();
	                    dLong = -position.x * longitudeSensivity;
	                    dLat = position.y * latitudeSensivity;

	                    velocity += new Vector2(dLat, dLong);
	           
	                //      Also implement tap controls

	                if (velocity.sqrMagnitude > boundary * boundary)
	                {
	                    float dt = Time.deltaTime;

	                    Vector2 prevVelocity = velocity;
	                    velocity -= dt * damping * velocity;
	                    if (Vector2.Dot(velocity, prevVelocity) <= 0)
	                        velocity = Vector2.zero;

	                    latitude += dt * velocity.x;
	                    longitude += dt * velocity.y;

	                    latitude = Mathf.Clamp(latitude, 0 + boundary, Mathf.PI - boundary);
	                    longitude = Mathf.Repeat(longitude, 2 * Mathf.PI);

	                    relativePosition = SphericalToCartesian(longitude, latitude, orbitRadius);
	                }
	              
	                this.transform.position = this.realTarget.transform.position + this.relativePosition;
                	this.transform.LookAt(this.realTarget.transform);

///////
private Vector3 SphericalToCartesian(float longitude, float latitude, float radius)
    {
        float x = radius * Mathf.Sin(latitude) * Mathf.Cos(longitude);
        float y = radius * Mathf.Cos(latitude);
        float z = radius * Mathf.Sin(latitude) * Mathf.Sin(longitude);
        return new Vector3(x, y, z);
    }
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы