How to calculate the trajectory of bullet in Unity2D? - c#

I'm doing the 2D game with bullets moving in parabola, but before I shoot the projectile I want to be able to calculate its trajectory.
float velocity = Mathf.Min(Mathf.Max(distance, 1), 2.5f);
float cos = Mathf.Cos( (gameObject.transform.localEulerAngles.z + 90) * Mathf.Deg2Rad);
float sin = Mathf.Sin( (gameObject.transform.localEulerAngles.z + 90) * Mathf.Deg2Rad);
newGO.GetComponent<Rigidbody2D>().AddForce(velocity * new Vector3(cos, sin))
This code adds the rigidbody2d to my bullet (newGO). I try to count a point after 1 sec of flying using it:
Debug.Log(new Vector3(source.transform.position.x + velocity * 1 * cos, source.transform.position.y + velocity * sin * 1 + Physics2D.gravity.y * 0.5f * 1));
Unfortunately it doesn't return the correct result. What should I do?
Thanks for help and sorry for my English.

I think being a projectile you should use Rigidbody2D.velocity to set the initial velocity of the projectile rather than Rigidbody2D.AddForce. (Although the documentation does not recommend)
This simple script predicts where the attached object will be in a time determined by the variable "timeLimit" and moves a "target" gameobject to that point.
public class Velocity : MonoBehaviour {
public GameObject target;
private float HoriInitialSpeed = 5;
private float VertInitialSpeed = 5;
private float timeLimit = 2;
private float timeElapsed=0;
void Start ()
{
float HoriPredict = HoriInitialSpeed * timeLimit;
float VertiPredict = VertInitialSpeed* timeLimit + (0.5f * Physics2D.gravity.y * timeLimit * timeLimit);
target.transform.Translate(HoriPredict, VertiPredict,0);
GetComponent<Rigidbody2D>().velocity = new Vector2(HoriInitialSpeed, VertInitialSpeed);
}
void Update () {
timeElapsed += Time.deltaTime;
if(timeElapsed >= timeLimit)
{
//stop the bullet
GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
GetComponent<Rigidbody2D>().gravityScale = 0;
}
}
}
Note: the bullet and the target must be in the same point inicially

Related

Clamp RotateAround object Unity

I am making a script to rotate my camera around a sphere but I need to clamp the y axis so the camera does not co over the polls of the sphere I am using rotate around to move my camera.
Thanks!
My current code
public float sensitivity = 1;
public float moveSpeed = 10;
public float maxUp = 45f;
public float maxDown = -45f;
public Transform target;
void Update()
{
transform.LookAt(target);
float HorizontalAxis = Input.GetAxis("Horizontal") * moveSpeed;
float VerticalAxis = Input.GetAxis("Vertical") * moveSpeed;
if (HorizontalAxis >= 1 || VerticalAxis >= 1 || HorizontalAxis <= -1 || VerticalAxis <= -1)
{
Quaternion targetPos = transform.rotation;
targetPos.x += HorizontalAxis * sensitivity;
targetPos.y += VerticalAxis * sensitivity;
transform.RotateAround(target.position, Vector3.left, targetPos.y);
transform.RotateAround(target.position, Vector3.up, targetPos.x);
}
}
Your code makes no sense to begin with.
You do
Quaternion targetPos = transform.rotation;
targetPos.x += HorizontalAxis * sensitivity;
targetPos.y += VerticalAxis * sensitivity;
Just to then use these as parameters in
transform.RotateAround(target.position, Vector3.left, targetPos.y);
transform.RotateAround(target.position, Vector3.up, targetPos.x);
A Quaternion has not three but four components x, y, z and w and they move in ranges between -1 and 1. You never touch the individual component of a Quaternion except you really know exactly what you are doing!
You rather simply want to use the HorizontalAxis and VerticalAxis directly as the parameters to RotateAround.
You could rather simply remember and clamp how much you already rotated like e.g.
private float rotatedY;
private void Update()
{
transform.LookAt(target);
// why two different multipliers anyway though?
var HorizontalAxis = Input.GetAxis("Horizontal") * moveSpeed * sensitivity;
var VerticalAxis = Input.GetAxis("Vertical") * moveSpeed * sensitivity;
// would a positive rotation exceed the maxUp?
if(rotatedY + VerticalAxis > maxUp)
{
// then rotate only so much that you terminate exactly on maxUp
VerticalAxis = maxUp - rotatedY;
}
// would a negative rotation exceed the maxDown?
else if(rotatedY + VerticalAxis < maxDown)
{
// then you rotate only that much that you terminate exactly on maxDown
VerticalAxis = maxDown - rotatedY;
}
transform.RotateAround(target.position, Vector3.left, VerticalAxis);
transform.RotateAround(target.position, Vector3.up, HorizontalAxis);
// sum up how much you already rotated vertically
rotatedY += VerticalAxis;
}

How to rotate around an object without using unity's built-in functions?

i want to rotate a cube around a 1x1 pipe with arrow keys. (left and right).
The problem is i cannot use built-in functions which sets transform's position and location directly. (Such as transform.lookAt, transform.Rotate or transform.RotateAround). Because I need the vector values of rotation's euler and position for multiple stuff before i modify the value of the transform i want to rotate.
I tried different techniques but no luck so far.
I tried using sin-cos for rotating but could not figure out how to make it work for both rotation and position.
_timer += Time.deltaTime * _larvaSpeed;
float x = -Mathf.Cos(_timer) * distanceBetweenCenter;
float y = Mathf.Sin(_timer) * distanceBetweenCenter;
Here is what i want to achieve. By pressing right or left, move and rotate the object around the pipe.
The result i want. (If i pressed right arrow key a litte bit).
I would appreciate any help. Thank you!
here is the solution using circle mathematics and I strongly recommended not use it, it's just to understand the circular move using circle equation as #FaTaLL ask in the comments
Circle equation...
(x1 - x2)^2 + (y1 - y2)^2 = r^2
x1, y1 is the cube position
x2, y2 is the pipe position
r is the distance between cube and pipe;
using UnityEngine;
public class Rotating : MonoBehaviour
{
public GameObject pipe;
public float Delta;
Vector3 nextpos;
bool compareY;
bool next;
int switchx;
float storeVarAxis;
float x, y, r;
private void Start()
{
next = true;
switchx = 1;
compareY = true;
x = transform.position.x - pipe.transform.position.x;
y = transform.position.y - pipe.transform.position.y;
storeVarAxis = y;
r = Mathf.Sqrt(x * x + y * y);
}
private void Update()
{
if (next)
{
if (compareY == true)
{
y -= Delta * Time.deltaTime;
if (y <= -storeVarAxis)
{
y = -storeVarAxis;
compareY = false;
switchx = -1;
}
}
else
{
y += Delta * Time.deltaTime;
if (y >= storeVarAxis)
{
y = storeVarAxis;
compareY = true;
switchx = 1;
}
}
float v = r * r - y * y;
x = Mathf.Sqrt(Mathf.Abs(v));
nextpos = new Vector3(pipe.transform.position.x + x * switchx, pipe.transform.position.y + y, transform.position.z);
next = false;
}
transform.position = Vector3.MoveTowards(transform.position, nextpos, 1f * Time.deltaTime);
if(Vector3.Distance(transform.position, nextpos) < .05) transform.position = nextpos;
if (transform.position.x.Equals(nextpos.x) && transform.position.y.Equals(nextpos.y)) next = true;
}
}
well, the recommended way is using this simple script
using UnityEngine;
public class Rotating : MonoBehaviour
{
public float speed;
public GameObject pipe;
float r, angle;
Vector3 startpos;
private void Start()
{
r = Mathf.Abs(transform.position.y - pipe.transform.position.y);
angle = 0;
transform.position = pipe.transform.position;
startpos = transform.position;
}
void Update()
{
angle = angle + speed * Time.deltaTime;
transform.rotation = Quaternion.EulerAngles(0,0, angle);
transform.position = startpos + (transform.rotation * new Vector3(r, 0, 0));
}
}
I think Quaternion * Vector3 is what you are looking for. Luckily the box's rotation in its own local coordinates is the same rotation you need to apply to the box's position.
public float speed; //how fast to rotate
public float radius; //radius of the cylinder
public float angle; //angle around it
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
angle = angle + speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
angle = angle - speed * Time.deltaTime;
}
//figure out the rotation (from euler angles i guess??)
var quat = Quaternion.EulerAngles(new Vector3(0, angle, 0));
//ok uh what is the box position?? lets just multiply
var unrotated_position = new Vector3(radius, 0, 0);
var rotated_position = quat * unrotated_position;
this.transform.position = rotated_position;
//oh yea and also rotate the box in its own local coordinates
this.transform.rotation = quat;
}

How to make a curved flight path?

How to make a bullet fly in an arc when shooting and hit the player.
As in this picture . I tried to use formulas from physics, the body is thrown at an angle to the horizon, that's what came of it . But the bullet flies away into the void
velocity = Mathf.Round(Vector3.Distance(lastpos, transform.position) / Time.deltaTime);
lastpos = transform.position;
Vector3 direction = PlayeCar.position - Vector3.zero;
float angle = Mathf.Atan2(direction.y, direction.x); // радианы
float x = velocity * Mathf.Cos(angle) + gravity * (time* time) / 2;
float y = velocity * Mathf.Sin(angle);
transform.position = new Vector2(x, y)
;
Sample orientative method could be (The script would be attached to the gun that shots, so when the code referes to transform, refers to the gun's transfom):
public void LaunchTarget()
{
Vector3 initialSpeed = transform.forward; //shot direction, gun's forward
GameObject go = GameObject.Instantiate(m_bullet);//reference to bullet prefab
//in case you need to randomize the shot speed
initialSpeed = transform.forward * Random.Range(m_minLaunchSpeed, m_maxLaunchSpeed);
//set the initial position of the bullet in the gun
go.transform.position = transform.position;
// shoot (give speed to the bullets rigidbody)
go.GetComponent<Rigidbody>().velocity = initialSpeed;
//initially disabled soas to see the bullet when shot
go.SetActive(true);
}
Hope that helps
I did it !!!! at the time of the bullet’s flight, I turn it toward the player in an intermittent manner. And after a while I delete it
void Start()
{
rigidbodyBullet = GetComponent<Rigidbody2D>();
Player = GameObject.Find("carPlayer").GetComponent<Transform>();
_distance = Vector3.Distance(Player.position, transform.position);
Invoke("DestroyArcBullet", 1.5f);
limitDistance = _distance / 1.3f;
}
void Update()
{
transform.position += transform.up * Time.deltaTime * 5f;
_distance = Vector3.Distance(Player.position, transform.position);
if (_distance < limitDistance)
{
var turn = Quaternion.Lerp(transform.rotation,
Quaternion.LookRotation(Vector3.forward, Player.position - transform.position), Time.deltaTime * 2);
rigidbodyBullet.MoveRotation(turn.eulerAngles.z);
}
if (this.transform.position.y + this.transform.position.y <= -10 || this.transform.position.y + this.transform.position.y >= 10
|| this.transform.position.x + this.transform.position.x <= -10 || this.transform.position.x + this.transform.position.x >= 10)
{
Destroy(gameObject);
}
}

Unity Follow The Leader Behavior

I asked this question two years ago. Not ever having success, I abandoned the idea until recently.
I have since been able to semi-fix / replicate the mechanic. However, all the objects seem to jump to their next position, with some duplicating their "leader's" position.
The orange is the head, with the body parts being green.
As you can see from the commented out code below, I have tried multiple permutations to get the children to follow their leader smoothly with the distance between each body-part just being the circle colliders radius.
My thought was, if the "leader" has moved the distance of the radius, then the follower can move towards the leaders old position. This give the leader time to move.
But the only one that seems to semi work, is the un-commented one.
Can anyone see the problem?
FollowTheLeader.cs
public class FollowTheLeader : MonoBehaviour
{
[Header("Head")]
public GameObject bodyPart;
public int bodyLength = 6;
[Header("Move Speed")]
[Range(0.25f, 2.0f)] public float moveMin = 0.5f;
[Range(0.25f, 2.0f)] public float moveMax = 2.0f;
[Header("Change Directions")]
[Range(0.25f, 2.0f)] public float changeMin = 0.5f;
[Range(0.25f, 2.0f)] public float changeMax = 2.0f;
[SerializeField]
private Vector2 oldPosition;
public Vector2 OldPosition { get => oldPosition; set => oldPosition = value; }
[SerializeField]
private Vector2 moveDirection = new Vector2(0, -1);
public Vector2 MoveDirection { get => moveDirection; set => moveDirection = value; }
[Header("Child")]
public int index;
public bool isChild;
public FollowTheLeader leader;
public float leaderDistance;
private CircleCollider2D m_collider2D;
private Rigidbody2D body2d;
private float moveSpeed;
private float moveTimePassed;
private float changeDirInterval;
private void Awake()
{
m_collider2D = GetComponent<CircleCollider2D>();
body2d = GetComponent<Rigidbody2D>();
AddBodyParts();
DefineDirection(moveDirection);
}
private void AddBodyParts()
{
if (isChild || bodyPart == null)
return;
//The head will generate its body parts. Each body part will have reference to the one before it.
FollowTheLeader temp = this;
for (int i = 1; i <= bodyLength; i++)
{
GameObject bp = Instantiate(bodyPart, transform);
bp.transform.SetParent(null);
//bp.transform.position = transform.position;
bp.transform.position = new Vector2(i * m_collider2D.radius, 0);
bp.name = $"Body {i}";
FollowTheLeader c = bp.AddComponent<FollowTheLeader>();
c.isChild = true;
c.index = i;
c.OldPosition = bp.transform.position;
c.leader = temp;
// cache the parent for the next body part
temp = c;
}
}
private void Start()
{
OnNewDirection();
}
private void FixedUpdate()
{
//Store the old postion for the next child
OldPosition = body2d.position;
// If child
if (isChild)
{
// Calculate the leaders distance
leaderDistance = Vector2.Distance(OldPosition, leader.OldPosition);
// We only want to move if the parent is as far away as the m_collider2D.radius.
if (leaderDistance < m_collider2D.radius)
return;
// BARELY ANY MOVEMENT
//body2d.MovePosition(leader.OldPosition.normalized);
//body2d.MovePosition(leader.OldPosition.normalized * moveSpeed);
//body2d.MovePosition(leader.OldPosition.normalized * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition.normalized * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition.normalized * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
//FLYS ALL OVER THE PLACE
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * moveSpeed);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * m_collider2D.radius * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition.normalized * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
// BARELY ANY MOVEMENT
//body2d.MovePosition(leader.OldPosition * moveSpeed);
//body2d.MovePosition(leader.OldPosition * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(leader.OldPosition * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
//FLYS ALL OVER THE PLACE
//body2d.MovePosition(body2d.position + leader.OldPosition);
//body2d.MovePosition(body2d.position + leader.OldPosition * moveSpeed);
//body2d.MovePosition(body2d.position + leader.OldPosition * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * parentDistance * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * m_collider2D.radius * moveSpeed * Time.deltaTime);
//body2d.MovePosition(body2d.position + leader.OldPosition * m_collider2D.radius * parentDistance * moveSpeed * Time.deltaTime);
// KINDA FOLLOWS BUT ALL SEEM TO JUMP INTO THE SAME POSITION AS SEEN IN THE GIF
body2d.MovePosition(leader.OldPosition);
return;
}
// HEAD ONLY
// Countdown to next direction change
moveTimePassed += Time.deltaTime;
if (moveTimePassed >= changeDirInterval)
{
OnNewDirection();
}
// Calculate the next position
body2d.MovePosition(body2d.position + MoveDirection.normalized * moveSpeed * Time.deltaTime);
}
public void OnNewDirection()
{
moveTimePassed = 0;
moveSpeed = Random.Range(moveMin, moveMax);
changeDirInterval = Random.Range(changeMin, changeMax);
RandomDirection();
}
private void RandomDirection()
{
switch (Random.Range(0, 4))
{
case 0:
DefineDirection(Vector2.up);
break;
case 1:
DefineDirection(Vector2.right);
break;
case 2:
DefineDirection(Vector2.down);
break;
case 3:
DefineDirection(Vector2.left);
break;
default:
DefineDirection(Vector2.down);
break;
}
}
public void DefineDirection(Vector2 direction)
{
if (direction.Equals(Vector2.up))
{
MoveDirection = Vector2.up;
}
if (direction.Equals(Vector2.down))
{
MoveDirection = Vector2.down;
}
if (direction.Equals(Vector2.left))
{
MoveDirection = Vector2.left;
}
if (direction.Equals(Vector2.right))
{
MoveDirection = Vector2.right;
}
}
}
Many different ways you can approach it but let me show you one way.
Snake - moves the leader forward, creates new points in the path, manages minions
Path - ring buffer with of all the points
Minion - follow the path based on the distance from the leader
Here's an example with gizmos showing:
Green is the leader
Red is the head of the path
Blue is the tail of the path
The snake is where the main logic is at.
The snake moves forward automatically. When the distance between the leader and the last point is greater than RADIUS we create a new point. We then move all of the minions along the path of points.
public class Snake : MonoBehaviour
{
public const float RADIUS = 1f; // distance between minions
public const float MOVE_SPEED = 1f; // movement speed
public Vector2 dir = Vector2.up; // movement direction
public float headDist = 0f; // distance from path 'head' to leader (used for lerp-ing between points)
public Path path = new Path(1); // path points
public List<Minion> minions = new List<Minion>(); // all minions
public Minion Leader => minions[0];
void Awake()
{
path.Add(this.transform.position);
AddMinion(new Knight());
}
void AddMinion(Minion minion)
{
// Initialize a minion and give it an index (0,1,2) which is used as offset later on
minion.Init(minions.Count);
minions.Add(minion);
minion.MoveOnPath(path, 0f);
// Resize the capacity of the path if there are more minions in the snake than the path
if (path.Capacity <= minions.Count) path.Resize();
}
void FixedUpdate()
{
MoveLeader();
MoveMinions();
}
void MoveLeader()
{
// Move the first minion (leader) towards the 'dir'
Leader.transform.position += ((Vector3)dir) * MOVE_SPEED * Time.deltaTime;
// Measure the distance between the leader and the 'head' of that path
Vector2 headToLeader = ((Vector2)Leader.transform.position) - path.Head().pos;
// Cache the precise distance so we can reuse it when we offset each minion
headDist = headToLeader.magnitude;
// When the distance between the leader and the 'head' of the path hits the threshold, spawn a new point in the path
if (headDist >= RADIUS)
{
// In case leader overshot, let's make sure all points are spaced exactly with 'RADIUS'
float leaderOvershoot = headDist - RADIUS;
Vector2 pushDir = headToLeader.normalized * leaderOvershoot;
path.Add(((Vector2)Leader.transform.position) - pushDir);
// Update head distance as there is a new point we have to measure from now
headDist = (((Vector2)Leader.transform.position) - path.Head().pos).sqrMagnitude;
}
}
void MoveMinions()
{
float headDistUnit = headDist / RADIUS;
for (int i = 1; i < minions.Count; i++)
{
Minion minion = minions[i];
// Move minion on the path
minion.MoveOnPath(path, headDistUnit);
// Extra push to avoid minions stepping on each other
Vector2 prevToNext = minions[i - 1].transform.position - minion.transform.position;
float distance = prevToNext.magnitude;
if (distance < RADIUS)
{
float intersection = RADIUS - distance;
minion.Push(-prevToNext.normalized * RADIUS * intersection);
}
}
}
}
Path is a ring buffer, Head() gives you the newest point that was added, you can use Head(index) to get the head and offset it in a direction(+/-). Minions use it to fetch points that are just behind the head: path.Head(-1).
public class Path
{
public Vector2[] Points { get; private set; }
public int Capacity => Points.Length;
int head;
public Path(int capacity)
{
head = 0;
Points = new Vector2[capacity];
}
public void Resize()
{
Vector2[] temp = new Vector2[Capacity * 2];
for (int i = 0; i < temp.Length; i++)
{
temp[i] = i < Capacity ? Head(i + 1) : Tail();
}
head = Capacity - 1;
Points = temp;
}
public void Add(Vector2 pos)
{
int prev = Mod(head, Capacity);
Next();
int next = Mod(head, Capacity);
Points[next].pos = pos;
}
public Vector2 Head()
{
return Points[head];
}
public Vector2 Head(int index)
{
return Points[Mod(head + index, Capacity)];
}
public Vector2 Tail()
{
return Points[Mod(head + 1, Capacity)];
}
public Vector2 Tail(int index)
{
return Points[Mod(head + 1 + index, Capacity)];
}
void Next()
{
head++;
head %= Capacity;
}
int Mod(int x, int m)
{
return (x % m + m) % m;
}
}
A minion contains an index, which tells us the placement of the minion within the snake (first, second, third). We use this index to get the two points needed for interpolation. path.Head(-0) will give us the leader's point. path.Head(-1) will give us the first minion's point.
public class Minion : MonoBehaviour
{
int index;
public Init(int index)
{
this.index = index;
}
// Move the minion along the path
public void MoveOnPath(Path path, float dist)
{
Vector2 prev = path.Head(-index);
Vector2 next = path.Head(-index + 1);
// Interpolate the position of the minion between the previous and the next point within the path. 'dist' is the distance between the 'head' of the path and the leader
this.transform.position = Vector2.Lerp(prev.pos, next.pos, dist);
}
// Push the minion to avoid minions stepping on each other
public void Push(Vector2 dir)
{
this.transform.position += (Vector3)dir;
}
}
I've stripped out a lot of code to make the example simpler. I hope you get the basic idea and will be able to implement your own solution.
I tried recreating this scenario in 3D and got somewhat the same behaviour as yours.
First, you want to use twice the radius, as each child would otherwise overlap half of the parent since it is the center of the circle that is being moved.
I used a different approach to move the children than you did. The result is a smooth, snake-like motion:
The code is simple enough:
First I rotate the child to point its forward axis at the leader's position
Second the length from the current position to the desired position is calculated. I subtract twice the radius, as the new position would otherwise result in overlapping spheres
I use the translate function to move the GameObject in the forward direction using the calculated magnitude.
// KINDA FOLLOWS BUT ALL SEEM TO JUMP INTO THE SAME POSITION AS SEEN IN THE GIF
//body2d.MovePosition(leader.OldPosition);
transform.LookAt(leader.transform);
float length = leaderDistance - (m_collider2D.radius * 2);
transform.Translate(transform.forward * length, Space.World);
return;
The result is a smooth, predictable motion. You can even turn off kinematic on the rigidbody to enable collisions.
Hope that helped you.

Why is my camera orbit flying off in the negative z?

I lifted most of this code from a year-old unity thread. Whenever I run it, my camera goes running off in the negative z direction very quickly. I've been poking at the variables all day, but nothing is making it click for me.
The z changes by 5 units every frame, which is exactly what I have set for the camera distance. This seems like the key to understanding the issue. Part of my problem is that I only barely grasp moving objects around using transforms and Euler angles. Thank you for your time.
public GameObject cameraTarget = null;
public float cameraSpeedX = 120.0f; //x sensitivity
public float cameraSpeedY = 120.0f; //y sensitivity
public float cameraVelocityX = 0.0f;
public float cameraVelocityY = 0.0f;
public float cameraRotationX = 0.0f;
public float cameraRotationY = 0.0f;
public float cameraLimitMinY = -20f;
public float cameraLimitMaxY = 80f;
public float cameraDistance = 5.0f;
public float cameraDdistanceMin = 0.5f;
public float cameraDistanceMax = 15.0f;
// Use this for initialization
void Start () {
gameObject.AddComponent<MeshFilter>();
gameObject.AddComponent<MeshRenderer>();
Vector3 angles = transform.eulerAngles;
cameraRotationX = angles.x;
cameraRotationY = angles.y;
// Make the rigid body not change rotation
if(GetComponent<Rigidbody>()){GetComponent<Rigidbody>().freezeRotation = true;}
cameraTarget = gameObject;
}
void LateUpdate(){
if (cameraTarget){
if (Input.GetMouseButton(1)){
cameraVelocityX += cameraSpeedX * Input.GetAxis("Mouse X") * 0.02f;
cameraVelocityY += cameraSpeedY * Input.GetAxis("Mouse Y") * 0.02f;
}
cameraRotationY += cameraVelocityX;
cameraRotationX -= cameraVelocityY;
cameraRotationX = ClampAngle(cameraRotationX, cameraLimitMinY, cameraLimitMaxY);
//Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
Quaternion toRotation = Quaternion.Euler(cameraRotationX, cameraRotationY, 0);
Quaternion rotation = toRotation;
Vector3 negDistance = new Vector3(0.0f, 0.0f, -cameraDistance);
Vector3 position = rotation * negDistance + cameraTarget.transform.position;
transform.rotation = rotation;
transform.position = position;
cameraVelocityX = Mathf.Lerp(cameraVelocityX, 0, Time.deltaTime * 2.0f);
cameraVelocityY = Mathf.Lerp(cameraVelocityY, 0, Time.deltaTime * 2.0f);
print ("POSITION:"+transform.position);
}
}
public static float ClampAngle(float angle, float min, float max){
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
For some reason I thought that putting the camera script and the game object generation in the same object was a good idea. The camera transforms were being applied to itself, which caused the camera to endlessly try to get behind itself. Thank you mprivat for your insight.

Categories