How to stop Roll Rotation in Mouse Look Script - c#

I am using FPS in Unity3D and I want only Pitch and Yaw. After some moves my Mouse Look Script start Rotating around z-axis (i.e. ROLL). How to stop that?
This is the Script that i am using for Mouse Look.
using UnityEngine;
using System.Collections;
public class MouseLooking : MonoBehaviour
{
float sensitivityX = 10f;
float sensitivityY = 10f;
public float minimumX = -360;
public float maximumX = 360;
public float minimumY = -60;
public float maximumY = 60;
public float delayMouse = 3;
public float noiseX = 0.1f;
public float noiseY = 0.1f;
public bool Noise;
private float rotationX = 0;
private float rotationY = 0;
private float rotationXtemp = 0;
private float rotationYtemp = 0;
private Quaternion originalRotation;
private float noisedeltaX;
private float noisedeltaY;
private float stunY;
private float breathHolderValtarget = 1;
private float breathHolderVal = 1;
private TouchScreenVal touch;
void Start ()
{
if (rigidbody)
rigidbody.freezeRotation = true;
originalRotation = transform.localRotation;
sensitivityX = sensitivityY = 10;
touch = new TouchScreenVal (new Rect (0, 0, Screen.width, Screen.height));
}
void Update ()
{
sensitivityY = sensitivityX;
// Screen.lockCursor = true;
stunY += (0 - stunY) / 20f;
if (Noise) {
noisedeltaX += ((((Mathf.Cos (Time.time) * Random.Range (-10, 10) / 5f) * noiseX) - noisedeltaX) / 100);
noisedeltaY += ((((Mathf.Sin (Time.time) * Random.Range (-10, 10) / 5f) * noiseY) - noisedeltaY) / 100);
} else {
noisedeltaX = 0;
noisedeltaY = 0;
}
#if UNITY_EDITOR
rotationXtemp += (Input.GetAxis ("Mouse X") * sensitivityX) + (noisedeltaX * breathHolderVal);
rotationYtemp += (Input.GetAxis ("Mouse Y") * sensitivityY) + (noisedeltaY * breathHolderVal);
rotationX += (rotationXtemp - rotationX) / delayMouse;
rotationY += (rotationYtemp - rotationY) / delayMouse;
#else
if (Constants.isGameOver == false) {
int count = Input.touchCount;
if (Input.touchCount > 0) {
for(int i =0 ; i< count ; i++)
{
Touch touch1 = Input.GetTouch (i);
if ((touch1.phase == TouchPhase.Moved ) || touch1.phase == TouchPhase.Stationary) {
rotationX = rotationXtemp + ( Input.GetTouch (i).deltaPosition.x * sensitivityX* Time.deltaTime) + (noisedeltaX * breathHolderVal);
rotationY = rotationYtemp + ( Input.GetTouch(i).deltaPosition.y * sensitivityY* Time.deltaTime) + (noisedeltaY * breathHolderVal);
// rotationX = rotationXtemp + (touch.OnDragDirection(true).x * sensitivityX * Time.deltaTime) + (noisedeltaX * breathHolderVal);
// rotationY = rotationYtemp + (-touch.OnDragDirection(true).y * sensitivityY * Time.deltaTime) + (noisedeltaY * breathHolderVal);
}
}
}
else
{
rotationX = rotationXtemp + (touch.OnDragDirection(true).x * sensitivityX * Time.deltaTime) + (noisedeltaX * breathHolderVal);
rotationY = rotationYtemp + (-touch.OnDragDirection(true).y * sensitivityY * Time.deltaTime) + (noisedeltaY * breathHolderVal);
}
}
#endif
if (rotationX >= 360) {
rotationX = 0;
rotationXtemp = 0;
}
if (rotationX <= -360) {
rotationX = 0;
rotationXtemp = 0;
}
rotationX = ClampAngle (rotationX, minimumX, maximumX);
rotationY = ClampAngle (rotationY, minimumY, maximumY);
rotationYtemp = ClampAngle (rotationYtemp, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis (rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis (rotationY + stunY, Vector3.left);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
breathHolderVal += (breathHolderValtarget - breathHolderVal) / 10;
#if !UNITY_EDITOR
rotationXtemp = rotationX;
rotationYtemp = rotationY;
#endif
}
public void Holdbreath (float val)
{
breathHolderValtarget = val;
}
public void Stun (float val)
{
stunY = val;
}
static float ClampAngle (float angle, float min, float max)
{
if (angle < -360.0f)
angle += 360.0f;
if (angle > 360.0f)
angle -= 360.0f;
return Mathf.Clamp (angle, min, max);
}
}

You can't use floats to store the x and y rotation, you need to store it all in a quaternion. So when you update from the mouse input, add it directly to the quaternion.
See Quaternion rotation without Euler angles for example.

Related

Change the script to also support Mouse drag?

I have a touch script to rotate the camera around the orbit. I am facing difficulty to add mouse click and drag function as well more like an || function to this script. The mouse function has Input.GetAxis("Mouse X") which detects the mouse position. How do I achieve it?
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
public float zoomDampening = 5.0f;
public float rotationSensitivity = 1f;
void LateUpdate()
{
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved) //Add mouse function
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
xDeg += touchposition.x * 20f * 0.002f;
yDeg -= touchposition.y * 20f * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.localRotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.localRotation = rotation;
}
I had to add Mouse X and Mouse Y axis to the floating variable and then it works as expected. The addition in the code is given below with the else statement:
else if (Input.GetMouseButton(0)) {
xDeg += Input.GetAxis("Mouse X") * rotationSensitivity;
yDeg -= Input.GetAxis("Mouse Y") * rotationSensitivity;
}
and for anyone who requires the full solution of mouse click and drag/touch and move and zoom in/out:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraOrbit : MonoBehaviour {
public Transform target;
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 5.0f;
public float ySpeed = 5.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public float zoomRate = 10.0f;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private Vector3 FirstPosition;
private Vector3 SecondPosition;
private Vector3 delta;
private Vector3 lastOffset;
private Vector3 lastOffsettemp;
public float rotationSensitivity = 1f;
void Start()
{
position = transform.localPosition;
rotation = transform.localRotation;
currentRotation = transform.localRotation;
desiredRotation = transform.localRotation;
distance = Vector3.Distance(transform.position, target.position);
currentDistance = distance;
desiredDistance = distance;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
}
void OnEnable() { Init(); }
public void Init()
{
// //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
if (!target)
{
GameObject go = new GameObject("Cam Target");
go.transform.position = transform.position + (transform.forward * distance);
target = go.transform;
}
}
void LateUpdate()
{
if (Input.touchCount == 2 && Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(1).phase == TouchPhase.Moved)
{
Touch touchZero = Input.GetTouch (0);
Touch touchOne = Input.GetTouch (1);
Vector2 touchZeroPreviousPosition = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePreviousPosition = touchOne.position - touchOne.deltaPosition;
float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;
float TouchDeltaMag = (touchZero.position - touchOne.position).magnitude;
float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;
desiredDistance += deltaMagDiff * Time.deltaTime * zoomRate * 0.0025f * Mathf.Abs(desiredDistance);
}
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
//CHANGE HERE
xDeg += touchposition.x * xSpeed * 0.002f;
//CHANGE HERE
yDeg -= touchposition.y * ySpeed * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
else
if (Input.GetMouseButton(0)) {
xDeg += Input.GetAxis("Mouse X") * rotationSensitivity;
yDeg -= Input.GetAxis("Mouse Y") * rotationSensitivity;
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.localRotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.localRotation = rotation;
////////Orbit Position
// affect the desired Zoom distance if we roll the scrollwheel
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
position = target.position - (rotation * Vector3.forward * currentDistance );
position = position - targetOffset;
transform.position = position;
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}

Touch to Zoom And Rotate script for Unity player

I had this unity player embedded in android studio activity.
It is a 3d model with animation, which I would like viewer to be able to zoom and view in different angle.
Script are from this link
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MobilemaxCamera : MonoBehaviour {
public Transform target;
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;
public float minDistance = .6f;
public float xSpeed = 5.0f;
public float ySpeed = 5.0f;
public int yMinLimit = -80;
public int yMaxLimit = 80;
public float zoomRate = 10.0f;
public float panSpeed = 0.3f;
public float zoomDampening = 5.0f;
private float xDeg = 0.0f;
private float yDeg = 0.0f;
private float currentDistance;
private float desiredDistance;
private Quaternion currentRotation;
private Quaternion desiredRotation;
private Quaternion rotation;
private Vector3 position;
private Vector3 FirstPosition;
private Vector3 SecondPosition;
private Vector3 delta;
private Vector3 lastOffset;
private Vector3 lastOffsettemp;
//private Vector3 CameraPosition;
//private Vector3 Targetposition;
//private Vector3 MoveDistance;
void Start() { Init(); }
void OnEnable() { Init(); }
public void Init()
{
//If there is no target, create a temporary target at 'distance' from the cameras current viewpoint
if (!target)
{
GameObject go = new GameObject("Cam Target");
go.transform.position = transform.position + (transform.forward * distance);
target = go.transform;
}
distance = Vector3.Distance(transform.position, target.position);
currentDistance = distance;
desiredDistance = distance;
//be sure to grab the current rotations as starting points.
position = transform.position;
rotation = transform.rotation;
currentRotation = transform.rotation;
desiredRotation = transform.rotation;
xDeg = Vector3.Angle(Vector3.right, transform.right);
yDeg = Vector3.Angle(Vector3.up, transform.up);
}
/*
* Camera logic on LateUpdate to only update after all character movement logic has been handled.
*/
void LateUpdate()
{
// If Control and Alt and Middle button? ZOOM!
if (Input.touchCount==2)
{
Touch touchZero = Input.GetTouch (0);
Touch touchOne = Input.GetTouch (1);
Vector2 touchZeroPreviousPosition = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePreviousPosition = touchOne.position - touchOne.deltaPosition;
float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;
float TouchDeltaMag = (touchZero.position - touchOne.position).magnitude;
float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;
desiredDistance += deltaMagDiff * Time.deltaTime * zoomRate * 0.0025f * Mathf.Abs(desiredDistance);
}
// If middle mouse and left alt are selected? ORBIT
if (Input.touchCount==1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 touchposition = Input.GetTouch(0).deltaPosition;
xDeg += touchposition.x * xSpeed * 0.002f;
yDeg -= touchposition.y * ySpeed * 0.002f;
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
}
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.rotation;
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.rotation = rotation;
if (Input.GetMouseButtonDown (1))
{
FirstPosition = Input.mousePosition;
lastOffset = targetOffset;
}
if (Input.GetMouseButton (1))
{
SecondPosition = Input.mousePosition;
delta = SecondPosition - FirstPosition;
targetOffset = lastOffset + transform.right * delta.x*0.003f + transform.up * delta.y*0.003f;
}
////////Orbit Position
// affect the desired Zoom distance if we roll the scrollwheel
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
position = target.position - (rotation * Vector3.forward * currentDistance );
position = position - targetOffset;
transform.position = position;
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
The zoom in and out work perfectly.
But the problem is, the rotate/pan is totally not working.
Anyone can give some help in this?
For the multi-touch, you have to use this script which I have given below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MultiTouch: MonoBehaviour
{
float initialFingersDistance;
Vector3 initialScale;
float rotationRate = 0.2f;
int direction = 1;
void LateUpdate()
{
if (Input.touches.Length == 1)
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Touch touch = Input.touches[0];
Quaternion desiredRotation = transform.rotation;
TouchLogic.Calculate();
if (Mathf.Abs(TouchLogic.turnAngleDelta) > 0)
{ // rotate
Vector3 rotationDeg = transform.eulerAngles;
rotationDeg.z = -TouchLogic.turnAngleDelta;
desiredRotation *= Quaternion.Euler(rotationDeg);
}
// not so sure those will work:
transform.rotation = desiredRotation;
// transform.Rotate(touch.deltaPosition.y * rotationRate, -touch.deltaPosition.x * rotationRate, 0, Space.World);
Vector3 rot = new Vector3(touch.deltaPosition.y * rotationRate, -touch.deltaPosition.x * rotationRate, transform.eulerAngles.z* rotationRate);
// transform.rotation = Quaternion.EulerAngles(rot);
}
}
else if (Input.touches.Length == 2)
{
Touch t1 = Input.touches[0];
Touch t2 = Input.touches[1];
if (t1.phase == TouchPhase.Began || t2.phase == TouchPhase.Began)
{
initialFingersDistance = Vector2.Distance(t1.position, t2.position);
initialScale = gameObject.transform.localScale;
}
else if (t1.phase == TouchPhase.Moved || t2.phase == TouchPhase.Moved)
{
var currentFingersDistance = Vector2.Distance(t1.position, t2.position);
// Debug.Log(currentFingersDistance);
////if (currentFingersDistance != initialFingersDistance)
//{
var scaleFactor = currentFingersDistance / initialFingersDistance;
gameObject.transform.localScale = initialScale * scaleFactor;
//}
float Dx = t1.position.x - transform.position.x;
float Dy = t1.position.y - transform.position.y;
//var cameraTransform = Camera.main.transform.InverseTransformPoint(0, 0, 0);
//transform.position = Camera.main.ScreenToWorldPoint(new Vector3(t2.position.x, t2.position.y, cameraTransform.z -0.5f));
Vector3 pos = t2.position;
//Vector3 pos = t1.position - t2.position;
Vector3 touchedPos = Camera.main.ScreenToWorldPoint(new Vector3(pos.x, pos.y, 10));
transform.position = Vector3.Lerp(transform.position, touchedPos, Time.deltaTime * 4);
// transform.position += touchedPos;
float pinchAmount = 0;
Quaternion desiredRotation = transform.rotation;
TouchLogic.Calculate();
if (Mathf.Abs(TouchLogic.pinchDistanceDelta) > 0)
{ // zoom
pinchAmount = TouchLogic.pinchDistanceDelta;
}
if (Mathf.Abs(TouchLogic.turnAngleDelta) > 0)
{ // rotate
Vector3 rotationDeg = Vector3.zero;
rotationDeg.z = -TouchLogic.turnAngleDelta;
desiredRotation *= Quaternion.Euler(rotationDeg);
}
// not so sure those will work:
transform.rotation = desiredRotation;
transform.position += Vector3.forward * pinchAmount;
}
}
}
}
For your touch control logic, you have to use this second script which I gave below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchLogic: MonoBehaviour
{
const float pinchTurnRatio = Mathf.PI / 2;
const float minTurnAngle = 0;
const float pinchRatio = 1;
const float minPinchDistance = 0;
const float panRatio = 1;
const float minPanDistance = 0;
/// <summary>
/// The delta of the angle between two touch points
/// </summary>
static public float turnAngleDelta;
/// <summary>
/// The angle between two touch points
/// </summary>
static public float turnAngle;
/// <summary>
/// The delta of the distance between two touch points that were distancing from each other
/// </summary>
static public float pinchDistanceDelta;
/// <summary>
/// The distance between two touch points that were distancing from each other
/// </summary>
static public float pinchDistance;
/// <summary>
/// Calculates Pinch and Turn - This should be used inside LateUpdate
/// </summary>
///
static public Touch LastTouch;
static public void Calculate()
{
pinchDistance = pinchDistanceDelta = 0;
turnAngle = turnAngleDelta = 0;
// if two fingers are touching the screen at the same time ...
if (Input.touchCount == 1)
{
Touch touch1 = Input.touches[0];
turnAngle = Angle(touch1.position, LastTouch.position);
float prevTurn = Angle(touch1.position + touch1.deltaPosition,
LastTouch.deltaPosition + LastTouch.position);
turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);
// ... if it's greater than a minimum threshold, it's a turn!
if (Mathf.Abs(turnAngleDelta) > minTurnAngle)
{
turnAngleDelta *= pinchTurnRatio;
}
else
{
turnAngle = turnAngleDelta = 0;
}
LastTouch =Input.touches[0];
}
else if (Input.touchCount == 2)
{
Touch touch1 = Input.touches[0];
Touch touch2 = Input.touches[1];
// ... if at least one of them moved ...
if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved)
{
// ... check the delta distance between them ...
pinchDistance = Vector2.Distance(touch1.position, touch2.position);
float prevDistance = Vector2.Distance(touch1.position - touch1.deltaPosition,
touch2.position - touch2.deltaPosition);
pinchDistanceDelta = pinchDistance - prevDistance;
// ... if it's greater than a minimum threshold, it's a pinch!
if (Mathf.Abs(pinchDistanceDelta) > minPinchDistance)
{
pinchDistanceDelta *= pinchRatio;
}
else
{
pinchDistance = pinchDistanceDelta = 0;
}
// ... or check the delta angle between them ...
turnAngle = Angle(touch1.position, touch2.position);
float prevTurn = Angle(touch1.position + touch1.deltaPosition,
touch2.position + touch2.deltaPosition);
turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);
// ... if it's greater than a minimum threshold, it's a turn!
if (Mathf.Abs(turnAngleDelta) > minTurnAngle)
{
turnAngleDelta *= pinchTurnRatio;
}
else
{
turnAngle = turnAngleDelta = 0;
}
}
}
}
static private float Angle(Vector2 pos1, Vector2 pos2)
{
Vector2 from = pos2 - pos1;
Vector2 to = new Vector2(1, 0);
float result = Vector2.Angle(from, to);
Vector3 cross = Vector3.Cross(from, to);
if (cross.z > 0)
{
result = 360f - result;
}
return result;
}
}
Both scripts are used in a single project. using these scripts you can easily rotate your 3d object.
Note: Please attach this both script in a single 3d object, so you can use this script easily.

How can I set the newPositions distance to be shorter closer to the original squadMembers positions?

I have 3 formations:
In each formation I'm calculating new positions to move to and add them to the List newPositions.
private void FormationTriangle()
{
newpositions = new List<Vector3>();
int height = Mathf.CeilToInt((Mathf.Sqrt(8 * squadMembers.Count + 1f) - 1f) / 2);
int slots = (int)(height * (height + 1f) / 2f);
float verticalModifier = 1.25f; // * 1.25f to increase horizontal space
float horizontalModifier = 0.8f; // * 0.8f to decrease "vertical" space
float width = 0.5f * (height - 1f);
Vector3 startPos = new Vector3(width * horizontalModifier, 0f, (float)(height - 1f) * verticalModifier);
int finalRowCount = height - slots + squadMembers.Count;
for (int rowNum = 0; rowNum < height && newpositions.Count < squadMembers.Count; rowNum++)
{
for (int i = 0; i < rowNum + 1 && newpositions.Count < squadMembers.Count; i++)
{
float xOffset = 0f;
if (rowNum + 1 == height)
{
// If we're in the last row, stretch it ...
if (finalRowCount != 1)
{
// Unless there's only one item in the last row.
// If that's the case, leave it centered.
xOffset = Mathf.Lerp(
rowNum / 2f,
-rowNum / 2f,
i / (finalRowCount - 1f)
) * horizontalModifier;
}
}
else
{
xOffset = (i - rowNum / 2f) * horizontalModifier;
}
float yOffset = (float)rowNum * verticalModifier;
Vector3 position = new Vector3(
startPos.x + xOffset, 0f, startPos.y - yOffset);
newpositions.Add(position);
}
}
move = true;
formation = Formation.Square;
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * gaps;
float posY = (index / columns) * gaps;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
for (int i = 0; i < squadMembers.Count; i++)
{
Vector3 pos = FormationSquarePositionCalculation(i);
//squadMembers[i].transform.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
squadMembers[i].transform.Rotate(new Vector3(0, -90, 0));
newpositions.Add(new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y));
}
move = true;
squareFormation = true;
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
newpositions = new List<Vector3>();
quaternions = new List<Quaternion>();
Vector3 center = transform.position;
float radius = (float)circleRadius / 2;
float angleIncrement = 360 / (float)numberOfSquadMembers;
for (int i = 0; i < numberOfSquadMembers; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
if (Terrain.activeTerrain == true)
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpositions.Add(pos);
quaternions.Add(rot);
}
move = true;
squareFormation = false;
formation = Formation.Triangle;
}
Then I'm moving the squadMembers to the newPositions:
private void MoveToNextFormation()
{
if (randomSpeed == false)
{
if (step.Length > 0)
step[0] = moveSpeed * Time.deltaTime;
}
for (int i = 0; i < squadMembers.Count; i++)
{
squadMembers[i].transform.LookAt(newpositions[i]);
if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) > 30f)
{
if (randomSpeed == true)
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[i]);
}
else
{
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpositions[i], step[0]);
}
}
if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) < threshold)
{
if (squareFormation == true)
{
Vector3 degrees = new Vector3(0, 0, 0);
Quaternion quaternion = Quaternion.Euler(degrees);
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternion, rotateSpeed * Time.deltaTime);
}
else
{
squadMembers[i].transform.rotation = Quaternion.Slerp(squadMembers[i].transform.rotation, quaternions[i], rotateSpeed * Time.deltaTime);
}
}
}
}
But if I want that the squadMembers will not move at all but will change to the next formation on the same position they are ? Or maybe to move just a little bit for example to distance 20 or 5 or 30 or 300 ?
I tried to add a distance check for the move:
if (Vector3.Distance(squadMembers[i].transform.position, newpositions[i]) > 30f)
So they are changing to the next formation when the distance more then 30.
But then the formation is not looking good. If for example it's the square formation the formation after they finished moving looks like a wave.
Screenshot example:
Wave formation

Moving the character controller to vector 3 position

I'm currently making my Boss AI perform a jump attack against the player, the AI use both navmesh and character controller for movment (navmash only for pathfinding), but I'm having a hard time trying to move the AI to the designated position. here is my code:
CharacterController chara;
[SerializeField]
Transform playerTran;
[SerializeField]
float gravity = 3.8f;
[SerializeField]
float jumpForce = 50F;
Vector3 moveVector = Vector3.zero;
[SerializeField]
Transform jumpCheck;
[SerializeField]
Transform jumpPos;
// Use this for initialization
void Start ()
{
chara = GetComponent<CharacterController>();
playerTran = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
// Update is called once per frame
void Update ()
{
chara.Move(moveVector);
if (chara.isGrounded)
{
transform.LookAt(playerTran);
}
moveVector -= Vector3.up * gravity * Time.deltaTime;
if (Input.GetKeyUp(KeyCode.J))
{
jumpCheck.position = new Vector3(playerTran.position.x, 0, playerTran.position.z);
float angle = findAngle( playerTran.position.x - transform.position.x , playerTran.position.z - transform.position.z);
Vector3 _toJumpPos = MakeJumpCricle(playerTran.position , jumpCheck.localScale.x/2, angle);
jumpPos.position = new Vector3(_toJumpPos.x, 0, _toJumpPos.z);
moveVector = Vector3.up * jumpForce * Time.deltaTime;
}
}
float findAngle(float x, float y)
{
float value;
value = (float)((Mathf.Atan2(x, y) / Mathf.PI) * 180);
if (value < 0)
{
value += 360;
}
Debug.Log(value);
return value;
}
Vector3 MakeJumpCricle( Vector3 center, float radius, float angle)
{
Vector3 pos = Vector3.zero;
pos.x = center.x - radius * Mathf.Sin(angle * Mathf.Deg2Rad);
pos.y = 0;
pos.z = center.z - radius * Mathf.Cos(angle * Mathf.Deg2Rad);
return pos;
}
I want to move the AI to the jumpPos with both forward and up vectors but I'm not sure to do this.
visualization of the code
code visualization
I found a good solution, I used a Bezier Curves to generate a path
posting it here so other might find it helpful.
refrence link
http://www.theappguruz.com/blog/bezier-curve-in-games
public LineRenderer jumpLine;
private int numberOfPoint = 50;
[SerializeField]
List<Vector3> pointPositions = new List<Vector3>();
CharacterController chara;
[SerializeField]
Transform playerTran;
[SerializeField]
float gravity = 3.8f;
[SerializeField]
float jumpForce = 50F;
Vector3 moveVector = Vector3.zero;
[SerializeField]
Transform jumpCheck;
[SerializeField]
Transform jumpPos;
[SerializeField]
Transform jumpHightOne;
bool movejump;
Vector3 pZero;
Vector3 pOne;
float time;
// Use this for initialization
void Start ()
{
chara = GetComponent<CharacterController>();
playerTran = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
jumpLine.positionCount = numberOfPoint;
jumpLine.gameObject.SetActive(false);
}
// Update is called once per frame
void Update ()
{
chara.Move(moveVector);
if (chara.isGrounded)
{
transform.LookAt(playerTran);
}
moveVector -= Vector3.up * gravity * Time.deltaTime;
if (Input.GetKeyUp(KeyCode.J))
{
jumpCheck.position = new Vector3(playerTran.position.x, 0, playerTran.position.z);
float angle = findAngle( playerTran.position.x - transform.position.x , playerTran.position.z - transform.position.z);
Vector3 _toJumpPos = MakeJumpCricle(playerTran.position , jumpCheck.localScale.x/2, angle);
Vector3 middlePoint = GetTheMiddlePoints(transform.position, playerTran.position, 0.5f);
jumpHightOne.position = new Vector3(middlePoint.x, jumpHightOne.position.y, middlePoint.z);
jumpPos.position = new Vector3(_toJumpPos.x, 0, _toJumpPos.z);
//moveVector = Vector3.up * jumpForce * Time.deltaTime;
//movejump = true;
DrawLinerBezierCurves();
}
if (movejump)
{
//MoveTowardsTarget(jumpPos.position);
}
}
Vector3 GetTheMiddlePoints(Vector3 origin, Vector3 destination, float middlepointfactor)
{
return (destination - origin) * middlepointfactor + origin;
// (destination - origin) * 0.5f;
}
float findAngle(float x, float y)
{
float value;
value = (float)((Mathf.Atan2(x, y) / Mathf.PI) * 180);
if (value < 0)
{
value += 360;
}
//Debug.Log(value);
return value;
}
Vector3 MakeJumpCricle( Vector3 center, float radius, float angle)
{
Vector3 pos = Vector3.zero;
pos.x = center.x - radius * Mathf.Sin(angle * Mathf.Deg2Rad);
pos.y = 0;
pos.z = center.z - radius * Mathf.Cos(angle * Mathf.Deg2Rad);
return pos;
}
void MoveTowardsTarget(Vector3 targetPostios)
{
var offset = targetPostios - transform.position;
if (offset.magnitude > .1f)
{
offset = offset.normalized * 15;
chara.Move(offset * Time.deltaTime);
}
else
{
movejump = false;
}
}
// line Bezier Curves
Vector3 CalculateBezierCurvesPoints(float t , Vector3 p0, Vector3 p1 )
{
return p0 + t * (p1 - p0);
// P = P0 + t(P1 – P0) , 0 < t < 1
}
// line Bezier Curves
Vector3 CalculateBezierCurvesPoints(float t, Vector3 p0, Vector3 p1, Vector3 p2)
{
float u = 1 - t;
float uu = u * u;
float tt = t * t;
Vector3 p = uu * p0;
p = p + 2 * u * t * p1;
p = p + tt * p2;
return p;
//P = (1-t)^2 P0 + 2 (1-t) t P1 + t^2 P2 , 0 < t < 1
// uu u tt
// uu * p0 + 2 * u * t * p1 + tt * p2
}
void DrawLinerBezierCurves()
{
if (pointPositions.Count > 0)
{
pointPositions.Clear();
jumpLine.positionCount = 0;
jumpLine.positionCount = numberOfPoint;
}
for (int i = 1; i < numberOfPoint + 1; i++)
{
float t = i / (float) numberOfPoint;
if (!jumpLine.gameObject.activeInHierarchy)
{
jumpLine.gameObject.SetActive(true);
}
pointPositions.Add(CalculateBezierCurvesPoints(t, transform.position,jumpHightOne.position, jumpPos.position));
jumpLine.SetPosition(i - 1, pointPositions[i - 1]);
}
}

Messing up Vectors in C# (Unity Engine)

I'm new to programming in C# in Unity and there is some problems when moving in the z-axis. The problem is that I continue to move when I let go of the up button. However, when I move in the x-axis it is fine, as letting go of the button will stop the player. The code is below:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
public Vector3 motion = new Vector3();
private CharacterController controller;
private bool onGround;
private float xRot, yRot;
public static float X_ROTATION = 0;
public static float Y_ROTATION = 0;
private const float lookSpeed = 2.0f;
public void Start() {
controller = GetComponent<CharacterController>();
}
public void FixedUpdate() {
if(Screen.lockCursor) {
Vector3 impulse = new Vector3();
if(Input.GetKey(KeyCode.W)) impulse.z+=1;
if(Input.GetKey(KeyCode.A)) impulse.x-=1;
if(Input.GetKey(KeyCode.S)) impulse.z-=1;
if(Input.GetKey(KeyCode.D)) impulse.x+=1;
if(impulse.sqrMagnitude > 0) {
motion += Quaternion.Euler(new Vector3(0, xRot, 0)) * impulse.normalized * 0.05f;
}
if(onGround) {
if(Input.GetKey(KeyCode.Space)) {
motion.y += 0.2f;
}
}
motion.y -= 0.015f;
Vector3 oldMotion = motion;
Vector3 oldPos = controller.transform.localPosition;
controller.Move(motion);
Vector3 newPos = controller.transform.localPosition;
motion = newPos - oldPos;
onGround = oldMotion.y < -0.0001f && motion.y >= -0.0001f;
motion.x *= 0.8f;
motion.y *= 0.8f;
}
}
public void Update() {
if(Screen.lockCursor && Input.GetKeyDown(KeyCode.Escape)) {
Screen.lockCursor = false;
}
if(!Screen.lockCursor && Input.GetMouseButtonDown(0)) {
Screen.lockCursor = true;
}
if(Screen.lockCursor) {
xRot += Input.GetAxis("Mouse X") * lookSpeed;
yRot -= Input.GetAxis("Mouse Y") * lookSpeed;
if(yRot < -90) yRot = -90;
if(yRot > 90) yRot = 90;
if(xRot < -180) xRot += 360;
if(xRot >= 180) xRot -= 360;
controller.transform.localRotation = Quaternion.Euler(new Vector3(yRot, xRot, 0));
}
Player.X_ROTATION = xRot;
}
}
The last few statments in FixedUpdate() where you have coded-
motion.x *= 0.8f;
motion.y *= 0.8f;
should also contain
motion.z *= 0.8f;
and may be u dont need-
motion.y *= 0.8f;
As Gkills said, you should fix the "depletion" of motion.y for motion.z at the end.
Additionally, you should probably want to swap
motion += Quaternion.Euler(new Vector3(0, xRot, 0)) * impulse.normalized * 0.05f;
for
motion += transform.rotation * impulse.normalized * 0.05f;
Then zero out the impulse.y component to prevent the player flying.
Finally you might want to use Time.deltaTime in your Update (so mouse look is frame rate independent)

Categories