Skip to content

Instantly share code, notes, and snippets.

@runette
Created April 14, 2020 11:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save runette/7ed27db21e145a59325ae713d8c4fcc7 to your computer and use it in GitHub Desktop.
Save runette/7ed27db21e145a59325ae713d8c4fcc7 to your computer and use it in GitHub Desktop.
Movement and Interaction script
//https://stackoverflow.com/questions/58328209/how-to-make-a-free-fly-camera-script-in-unity-with-acceleration-and-decceleratio
// copyright Runette Software Ltd, 2020. All rights reserved
using UnityEngine;
using UnityEngine.InputSystem;
using Zinnia.Pointer;
using Zinnia.Cast;
public class FlyingCam : MonoBehaviour
{
[Header("Constants")]
public Camera self;
//unity controls and constants input - keyboard
public float AccelerationMod;
public float DeccelerationMod;
public float XAxisSensitivity;
public float YAxisSensitivity;
//unity controls - VR
public float HorizontalMod;
public float VerticalMod;
public float PandSensitvity;
public float ZoomSensitivity;
[Space]
[Range(0, 89)] public float MaxXAngle = 60f;
[Space]
private bool editSelected = false;
private Transform selectedRigibody;
private float selectedDistance;
private Vector3 speed;
private float _rotationX;
private Transform currentPointerHit;
// Update is called once per frame
private void Update()
{
transform.Translate(speed);
OVRInput.Update();
speed -= speed / DeccelerationMod;
}
private void FixedUpdate()
{
OVRInput.FixedUpdate();
}
//
// Methods for Input System based UIs
//
//
// link this to an a 2D axis control for in plane movement
//
public void HandleMove(InputAction.CallbackContext context)
{
Vector3 speed_input = context.ReadValue<Vector2>().normalized * AccelerationMod;
speed += Quaternion.AngleAxis(90.0f, Vector3.right) * speed_input;
}
//
// link this to a 1D axis control for vertical movement
//
public void HandleVertical(InputAction.CallbackContext context)
{
Vector3 speed_input = context.ReadValue<Vector2>().normalized * AccelerationMod;
speed += speed_input;
}
//
// Link this to a 2D axis control to control pan and zoom
//
public void HandlePanZoom(InputAction.CallbackContext context)
{
Vector2 pz_input = context.ReadValue<Vector2>().normalized;
transform.LookAt(Vector3.zero);
float pan = pz_input.x;
Pan(pan);
float zoom = pz_input.y * 0.1f;
Zoom(zoom);
}
//
// Link this to the mouse delta control
//
public void HandleMouseRotation(InputAction.CallbackContext context)
{
Vector2 input = context.ReadValue<Vector2>();
if (!editSelected)
{
//mouse input
var rotationHorizontal = XAxisSensitivity * input.x;
var rotationVertical = YAxisSensitivity * input.y;
//applying mouse rotation
// always rotate Y in global world space to avoid gimbal lock
transform.Rotate(Vector3.up * rotationHorizontal, Space.World);
var rotationY = transform.localEulerAngles.y;
_rotationX += rotationVertical;
_rotationX = Mathf.Clamp(_rotationX, -MaxXAngle, MaxXAngle);
transform.localEulerAngles = new Vector3(-_rotationX, rotationY, 0);
}
else
{
Ray ray = self.ScreenPointToRay(Mouse.current.position.ReadValue());
Vector3 newPos = ray.GetPoint(selectedDistance);
if (selectedRigibody != null)
{
selectedRigibody.gameObject.SendMessage("MoveTo", newPos, SendMessageOptions.DontRequireReceiver);
}
}
}
//
// use this for processing any key inputs
//
public void HandleKeyInput(InputAction.CallbackContext context)
{
InputAction action = context.action;
if (action.name == "Edit" && !Global.EditSession)
{
Global.EditSession = true;
}
if (action.name == "EndEdit" && Global.EditSession)
{
Global.EditSession = false;
EventManager eventManager = Global.Map.GetComponent<EventManager>();
eventManager.OnEditsessionEnd.Invoke();
}
if (action.name == "Exit")
{
Debug.Log("Exit");
Application.Quit();
}
}
//
// Link this to the mouse click control
//
public void HandleMouseClick(InputAction.CallbackContext context)
{
InputAction action = context.action;
int button = 0;
switch (action.name)
{
case "Select":
button = 0;
break;
case "MultiSelect":
button = 1;
break;
}
if (action.phase == InputActionPhase.Canceled && Global.EditSession)
{
UnClickHandler(button);
}
else if (action.phase == InputActionPhase.Started && !editSelected && Global.EditSession)
{
ClickHandler(button);
}
}
private void ClickHandler(int button)
{
RaycastHit hitInfo = new RaycastHit();
Vector3 mousePos = Input.mousePosition;
Ray ray = self.ScreenPointToRay(mousePos);
//Debug.DrawRay(ray.origin, ray.direction * 100f, Color.yellow, 1000f);
bool hit = Physics.Raycast(ray, out hitInfo);
if (hit)
{
selectedRigibody = hitInfo.transform;
if (selectedRigibody != null)
{
editSelected = true;
select(selectedRigibody, button));
selectedDistance = hitInfo.distance;
}
}
else
{
editSelected = false;
}
}
private void UnClickHandler(int button)
{
editSelected = false;
if (selectedRigibody != null)
{
unSelect(selectedRigibody, button);
selectedRigibody = null;
}
}
//
//
// Methods for VRTK based integratin to the VR UI
//
//
// Link this to a 2D control for in plane movement
//
public void Move(Vector2 axis)
{
Vector3 speed_input = axis.normalized * HorizontalMod;
speed += Quaternion.AngleAxis(90.0f, Vector3.right) * speed_input;
}
//
// Link this to a boolean control for movement up
//
public void Up(bool thisEvent)
{
if (thisEvent)
{
Vector3 speed_input = Vector3.up * VerticalMod;
speed += speed_input;
}
}
//
// link this to a boolean control for movement down
//
public void Down(bool thisEvent)
{
if (thisEvent)
{
Vector3 speed_input = Vector3.down * VerticalMod;
speed += speed_input;
}
}
//
// Link this to a 2d axis control for pan and zoom
//
public void PanZoom(Vector2 axis)
{
Vector2 pz_input = axis.normalized;
float pan = pz_input.x * PandSensitvity;
Pan(pan);
float zoom = pz_input.y * ZoomSensitivity;
Zoom(zoom);
}
//
// link to boolean action for when the ray hits a collider
//
// e.g VRTK Pointer Entering event
//
public void PointerHit(ObjectPointer.EventData data )
{
RaycastHit hitInfo = data.CurrentPointsCastData.HitData.Value;
currentPointerHit = hitInfo.transform;
selectedDistance = hitInfo.distance;
}
//
// link to boolean action for when the ray stops hiting a collider
//
// e.g VRTK Pointer Exiting event
//
public void PointerUnhit(ObjectPointer.EventData data)
{
if (!editSelected)
{
currentPointerHit = null;
selectedDistance = 0;
}
}
//
// link to boolean action for first event type
//
// you can have as many as you like, you just have to clone this call and change button value
//
public void triggerPressed(bool thisEvent)
{
if (currentPointerHit != null)
{
editSelected = true;
int button = 0;
select(currentPointerHit, 0);
}
}
public void gripPressed(bool thisEvent)
{
if (currentPointerHit != null)
{
editSelected = true;
select(currentPointerHit, 1);
}
}
//
// call this when any event type ends
//
public void triggerReleased(bool thisEvent)
{
editSelected = false;
if (currentPointerHit != null)
{
unSelect(currentPointerHit, 0);
}
}
//
// this is used to get data on the movement of the pointer to allow move events to be sent to enitties
//
// link to the StraightCaster Changed event
//
public void receiveRay(PointsCast.EventData data)
{
if (editSelected)
{
if (!data.IsValid)
{
Vector3 dir = data.Points[1] - data.Points[0];
dir = dir.normalized * selectedDistance;
moveTo(currentPointerHit, data.Points[0] + dir);
}
}
}
//
// Internal methods common to both UIs
//
private void Pan(float pan)
{
gameObject.transform.RotateAround(Vector3.zero, Vector3.down, pan);
}
private void Zoom(float zoom)
{
transform.Translate(Vector3.forward * Vector3.Distance(transform.position, Vector3.zero) * zoom);
}
private void moveTo(Transform target, Vector3 pos)
{
target.gameObject.SendMessage("MoveTo", pos, SendMessageOptions.DontRequireReceiver);
}
private void select(Transform target, int button)
{
target.gameObject.SendMessage("Selected", button, SendMessageOptions.DontRequireReceiver);
}
private void unSelect(Transform target, int button)
{
target.gameObject.SendMessage("UnSelected", button, SendMessageOptions.DontRequireReceiver);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment