I've been asked to look into creating a simple iterative application with Unity. This application has 2 major functions regarding the camera.
I'm new to this but I've managed to create two scripts that achieve these goals in isolation. Now I'm struggling to fit them together.
I'll start with the relevant code for user interaction.
First, I use TouchKit to set the delta values on each frame this is in Start
.
// set the delta on each frame for horizontal and vertical rotation
var oneTouch = new TKPanRecognizer();
oneTouch.gestureRecognizedEvent += (r) =>
{
HorizontalDelta += r.deltaTranslation.x * rotateSpeed * Time.deltaTime;
VerticalDelta -= r.deltaTranslation.y * rotateSpeed * Time.deltaTime;
};
// do the same for pinch
var pinch = new TKPinchRecognizer();
pinch.gestureRecognizedEvent += (r) =>
{
rotateDistance -= r.deltaScale * 200.0f * Time.deltaTime;
};
TouchKit.addGestureRecognizer(oneTouch);
TouchKit.addGestureRecognizer(pinch);
And on Update
:
VerticalDelta = Mathf.Clamp(VerticalDelta, verticalPivotMin, verticalPivotMax);
var direction = GetDirection(HorizontalDelta, VerticalDelta);
var currentTarget = targetsSwitched ? target2 : target;
transform.position = currentTarget.position - direction * rotateDistance;
transform.LookAt(currentTarget.position);
// ...
private Vector3 GetDirection(float x, float y)
{
Quaternion q = Quaternion.Euler(y, x, 0);
return q * Vector3.forward;
}
This works beautifully and does exactly what I want. The problem comes when I try to integrate this code with my camera moving script. This shows where I want to add the Update
code
void Update ()
{
if (currentlyMoving)
{
FocusTarget(currentTarget);
}
else
{
// accept user input if not moving
if (Input.GetKeyDown(KeyCode.Space))
{
SetMoveToTarget(mainTargetObject);
}
if (Input.GetKeyDown(KeyCode.Q))
{
SetMoveToTarget(subTargetObject1);
}
if (Input.GetKeyDown(KeyCode.E))
{
SetMoveToTarget(subTargetObject2);
}
}
}
These are the functions that actually move the camera:
void SetMoveToTarget(GameObject target)
{
if (currentlyMoving == false)
{
currentlyMoving = true;
fromRotation = currentTarget.transform.rotation;
currentTarget = target;
toRotation = currentTarget.transform.rotation;
timeStartedLerping = Time.time;
}
}
void FocusTarget(GameObject target)
{
float timeSinceStarted = Time.time - timeStartedLerping;
float percentageComplete = timeSinceStarted / (lerpSpeed);
transform.position = Vector3.MoveTowards(transform.position, target.transform.position, moveSpeed * Time.deltaTime);
transform.rotation = Quaternion.Lerp(fromRotation, toRotation, Mathf.Pow(percentageComplete, (float)1.2));
if (Vector3.Distance(transform.position, target.transform.position) < 0.1 && percentageComplete > 0.99)
{
transform.position = target.transform.position;
transform.rotation = target.transform.rotation;
currentlyMoving = false;
}
}
I think what I need to do (and I may be wrong on this) is set rotateDistance
to be the difference between the currentTarget
in the second script and currentTarget
in the first script.
Thank you in advance, it's quite a tricky one for me.
In the end I had to change how I was dealing with moving the camera in the first place. The problem was that moving to a set game object worked and was easy to set-up but it's much easier to integrate with the look script if you actually calculate when the next position of the camera should be and move to that.
I'm going to paste the working product here for posterity, it's missing some stuff from the end game but the camera is working.
using UnityEngine;
using UnityEngine.UI;
public class NewCamera : MonoBehaviour {
// targets
public GameObject target;
public GameObject target2;
// settings
public float RotateSpeed = 50.0f;
public float RotateDistance = 3;
public float CameraMoveSpeed = 20f;
public float VerticalPivotMin = 5;
public float VerticalPivotMax = 65;
public float MinZoomIn = 1.7f;
public float MaxZoomIn = 4f;
// private
private GameObject lookTarget;
private bool currentlyMoving = false;
private Vector3 targetVector;
private float timeStartedLerping;
private float HorizontalDelta;
private float VerticalDelta;
void Start ()
{
lookTarget = target;
var oneTouch = new TKPanRecognizer();
oneTouch.gestureRecognizedEvent += (r) =>
{
if (currentlyMoving == false)
{
HorizontalDelta += r.deltaTranslation.x * RotateSpeed * Time.deltaTime;
VerticalDelta -= r.deltaTranslation.y * RotateSpeed * Time.deltaTime;
VerticalDelta = Mathf.Clamp(VerticalDelta, VerticalPivotMin, VerticalPivotMax);
}
};
var pinch = new TKPinchRecognizer();
pinch.gestureRecognizedEvent += (r) =>
{
if (currentlyMoving == false)
{
RotateDistance -= r.deltaScale * 200.0f * Time.deltaTime;
RotateDistance = Mathf.Clamp(RotateDistance, MinZoomIn, MaxZoomIn);
}
};
TouchKit.addGestureRecognizer(oneTouch);
TouchKit.addGestureRecognizer(pinch);
}
void Update ()
{
if (currentlyMoving)
{
FocusTarget();
}
else
{
var direction = GetDirection(HorizontalDelta, VerticalDelta);
transform.position = lookTarget.transform.position - direction * RotateDistance;
transform.LookAt(lookTarget.transform.position);
}
}
public void OnButtonClick()
{
var currentTarget = target.GetInstanceID() == lookTarget.GetInstanceID() ? target : target2;
var nextTarget = currentTarget.GetInstanceID() == target.GetInstanceID() ? target2 : target;
var cameraPosition = transform.position;
var targetPosition = currentTarget.transform.position;
SetMoveToTarget(nextTarget, cameraPosition - targetPosition);
}
void SetMoveToTarget(GameObject moveTo, Vector3 offset)
{
currentlyMoving = true;
targetVector = moveTo.transform.position + offset;
lookTarget = moveTo;
}
void FocusTarget()
{
transform.position = Vector3.Lerp(transform.position, targetVector, CameraMoveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetVector) < 0.01)
{
transform.position = targetVector;
currentlyMoving = false;
}
}
private Vector3 GetDirection(float x, float y)
{
Quaternion q = Quaternion.Euler(y, x, 0);
return q * Vector3.forward;
}
}
If you want to use it for any reason, just add this script to a camera and set the two targets. I have to make a more robust version where you can add new targets easily but this will do for now.
Happy hacking!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With