Stopping my camera from getting to close - unity3d

This is my script (written in JavaScript), which creates a camera movement. I can't figure out how to make it so that I can get it to not move too close to the object (target). It is probably something simple, but I'm a noob at Unity.
If it's not possible to get it by modifying the existing code, could you suggest another way to get the desired motion?
#pragma strict
var target : Transform;
var localOffset = Vector3(0,0,0);
var finalPos : Vector3;
var currentPos : Vector3;
var speed = 0.01;
private var startTime: float;
private var journeyLength: float;
function Start() {
startTime = Time.time;
}
function Update () {
currentPos = transform.position;
finalPos = target.position + (target.up * localOffset.z);
finalPos = target.position + (target.forward * localOffset.x);
transform.LookAt(target.position);
journeyLength = Vector3.Distance(transform.position, finalPos);
var distCovered = (Time.time - startTime) * speed;
var fracJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(transform.position, finalPos, fracJourney);
}

I would use Vector3.Distance
function Update()
{
...
if (Vector3.Distance(target.position, transform.position) > 10) // Change '10' to any distance that you want as a minimum
{
transform.position = Vector3.Lerp(transform.position, finalPos, fracJourney);
}
Hope this helps :)

There's a small bug in your code, if you replace:
finalPos = target.position + (target.up * localOffset.z);
finalPos = target.position + (target.forward * localOffset.x);
with:
finalPos = target.position + (target.up * localOffset.z);
finalPos += (target.forward * localOffset.x);
will you get what you want?

Related

Problem rotating an object on its local orientation

Hello i am new in the forum! I hope i am in the right section! Im trying to rotate a camera (that rapresent the player POV) using the mouse delta and im rotating the camera in local coordinates not world coordinates and i want avoid gimbal lock effect. I read somewhere on the internet that for that purpose i have to use quaternions, and i read how to do that. The problem is that axis rotations works well moving in local orientation but one of the axis is losing its local orientation and it rotate following the world coordinates orientation. I will post the code and i hope someone can help me and telling me where im doing things wrong. Thanks!
public class Player : MonoBehaviour {
[Header("Camera")]
[SerializeField] private Camera _camera;
[SerializeField] private Vector2 _xMinMaxRotation = new Vector2(-90, 90);
[SerializeField] private Vector2 _yMinMaxRotation = new Vector2(-90, 90);
[SerializeField] private float _mouseXSensistivity = 1;
[SerializeField] private float _mouseYSensistivity = 1;
[SerializeField] private float _mouseZSensistivity = 1;
[SerializeField] private float _xStartRotation = 0;
[SerializeField] private float _yStartRotation = 0;
private Vector2 _mouseDelta;
private float _rotY, _rotX, _rotZ;
//public GameObject head;
// Start is called before the first frame update
void Start() {
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update() {
_mouseDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
MoveCamera();
}
private void MoveCamera() {
_rotX += _mouseDelta.x * _mouseXSensistivity * Time.deltaTime * 100;
_rotX = Mathf.Clamp(_rotX, _xMinMaxRotation.x, _xMinMaxRotation.y);
_rotY += _mouseDelta.y * _mouseYSensistivity * Time.deltaTime * 100;
_rotY = Mathf.Clamp(_rotY, _yMinMaxRotation.x, _yMinMaxRotation.y);
//Calculation for RotZ
if (Input.GetKey(KeyCode.Q)) {
_rotZ += +_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ > 25) _rotZ = 25;
}
else {
if (_rotZ > 0) {
_rotZ -= 2 * _mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ < 0) _rotZ = 0;
}
}
if (Input.GetKey(KeyCode.E)) {
_rotZ += -_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ < -25) _rotZ = -25;
}
else {
if (_rotZ < 0) {
_rotZ -= 2 * -_mouseZSensistivity * Time.deltaTime * 50;
if (_rotZ > 0) _rotZ = 0;
}
}
Quaternion currentRotation = Quaternion.identity;
currentRotation = currentRotation * Quaternion.AngleAxis(_rotX, transform.up);
currentRotation = currentRotation * Quaternion.AngleAxis(-_rotY, transform.right);
currentRotation = currentRotation * Quaternion.AngleAxis(_rotZ, transform.forward);
_camera.transform.localRotation = currentRotation;
//head.transform.position = _camera.transform.position;
//head.transform.rotation = _camera.transform.rotation;
}
The last part with quaternions is where im trying to calculate angles in order to properly rotate in local coordinates.
You don’t need to use quaternions at all.
You can use transform.EulerAngles instead of the transform.rotation or transform.localEulerAngles instead of transform.LocalRotation.
I messed up the capitalization I’m sure.
Say you wanted to rotate the camera 10 degrees along the local x axis. That would look something like
transform.localEulerAngles = transform.localEulerAngles.Add(10,0,0);
That’s it as far as I know. If you wanna read more about this,
transfrom.localEulerAngles
If your question was completely different, let me know and I can change or remove my answer.

Face other object using lerp in a coroutine

I want to have a coroutine to use the lerp function and so far I managed to do so partially. The characters will turn their position to face the target object. However, I want the characters to move their rotation starting from their own while what is currently happening is their rotation is set to some abstract value like X=0 and then it will start rotating them from there.
What I want to do is simply turn the character to face another transform smoothly. Here's the code:
public IEnumerator LookSlerpAt(Transform target, int seconds)
{
IsTurningHead = true;
Vector3 relativePos = target.position - this.transform.position;
Quaternion lookRotation = Quaternion.LookRotation(relativePos);
float elapsedTime = 0f;
float fraction = elapsedTime / seconds;
while (elapsedTime <= seconds)
{
this.transform.rotation = Quaternion.Lerp(target.rotation, lookRotation, fraction);
print($"rotation:{this.transform.rotation}");
elapsedTime += Time.deltaTime;
fraction = elapsedTime / seconds;
yield return Time.deltaTime;
}
IsTurningHead = false;
}
Thanks for your time
if you want to rotate smoothly to direction you could use that as coroutine: You specify the specified time to rotate and the velocity is automatically adjusted
public IEnumerator RotateToDirection(Transform transform, Vector3 positionToLook, float timeToRotate)
{
var startRotation = transform.rotation;
var direction = positionToLook - transform.position;
var finalRotation = Quaternion.LookRotation(direction);
var t = 0f;
while (t <= 1f)
{
t += Time.deltaTime / timeToRotate;
transform.rotation = Quaternion.Lerp(startRotation, finalRotation, t);
yield return null;
}
transform.rotation = finalRotation;
}

Unity Smooth 2D Camera following - Huge Issue :(

As you can see in the topic - I have a camera problem. I use a script (you can see below) and I have something like this - http://rapidgamesstudio.com/games/diggermachines/
What I want to achieve is a smooth following camera to player.
I've tried everything. I have about 50-60 fps and still this bug occures.
This is my camera code:
void Update() {
if(!player)
return;
//if(!isDiggableCamera) {
Vector3 point = Camera.main.WorldToViewportPoint(player.transform.position);
Vector3 delta = player.transform.position - Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, point.z)); //(new Vector3(0.5, 0.5, point.z));
Vector3 destination = transform.position + delta;
destination.z = transform.position.z;
transform.position = Vector3.SmoothDamp(transform.position, destination, ref velocity, dampTime);
//Vector3 destination = new Vector3(player.transform.position.x, player.transform.position.y, transform.position.z);
//transform.position = Vector3.SmoothDamp(transform.position, destination, ref velocity, dampTime);
//} else {
// startDigging(0, 0, 0);
//}
leftSite.position = new Vector3(leftSite.position.x, player.position.y, leftSite.position.z);
rightSite.position = new Vector3(rightSite.position.x,
player.position.y, rightSite.position.z);
}
I tried execute this code in Update(), FixedUpdate(), LateUpdate() even with all three - and still is the same problem.
Below code for updating player position:
//move player
float changableSpeedX = 5000.0f;
float changableSpeedY = 6000.0f;
Vector2 speed = new Vector2(x * Time.deltaTime * changableSpeedX,
y * Time.deltaTime * changableSpeedY);
//if(playerRigidbody.velocity.y + speed.y >= Game.game().activeMaxVelY)
// speed.y = Game.game().activeMaxVelY - playerRigidbody.velocity.y;
playerRigidbody.AddForce(speed);
//AddForce(speed);
//and checking max speed
protected void checkSpeed()
{
if(playerRigidbody.velocity.x > Game.game().activeMaxVelX)
playerRigidbody.velocity = new Vector2(Game.game().activeMaxVelX, playerRigidbody.velocity.y);
if(playerRigidbody.velocity.x < -Game.game().activeMaxVelX)
playerRigidbody.velocity = new Vector2(-Game.game().activeMaxVelX, playerRigidbody.velocity.y);
if(playerRigidbody.velocity.y > Game.game().activeMaxVelY)
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, Game.game().activeMaxVelY);
if(playerRigidbody.velocity.y < maxSpeedYGravity)
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, maxSpeedYGravity);
}
Could anyone help me?
If you need more code please let me know which part (because I don't want to add too much unnecessary code)
Might i suggest a lerp sir , in the update function use this
maincamera.transform.position = new vector3(maincamera.transform.position,player.transform.poistion,speed*Time.deltaTime);
Try This One !!!
private float xMax;
[SerializeField]
private float yMax;
[SerializeField]
private float xMin;
[SerializeField]
private float yMin;
private Transform target;
// Use this for initialization
void Start () {
target = GameObject.Find("Player").transform;
}
// Update is called once per frame
void LateUpdate () {
transform.position = new Vector3(Mathf.Clamp(target.position.x, xMin, xMax), Mathf.Clamp(target.position.y, yMin, yMax),transform.position.z);
}
}

Unity - Subject can move WASD, however WASD doesn't turn where camera points

I'm following some guide on character controls and have copied down the following script:
#pragma strict
var walkAcceleration : float = 5;
var walkDeacceleration : float =5;
#HideInInspector var walkDeaccelerationVolx : float;
#HideInInspector var walkDeaccelerationVolz : float;
var cameraObject : GameObject;
var maxWalkSpeed : float = 10;
#HideInInspector var horizontalMovement : Vector2;
//Jumping Variables
var jumpVelocity : float = 275;
var grounded : boolean = false;
var maxSlope : float = 60;
function Update () {
horizontalMovement = Vector2(rigidbody.velocity.x, rigidbody.velocity.z);
if(horizontalMovement.magnitude > maxWalkSpeed){
horizontalMovement = horizontalMovement.normalized;
horizontalMovement *= maxWalkSpeed;
}
rigidbody.velocity.x = horizontalMovement.x;
rigidbody.velocity.z = horizontalMovement.y;
if(Input.GetAxis("Horizontal") == 0 && Input.GetAxis("Vertical") ==0){
rigidbody.velocity.x = Mathf.SmoothDamp(rigidbody.velocity.x, 0, walkDeaccelerationVolx, walkDeacceleration);
rigidbody.velocity.z = Mathf.SmoothDamp(rigidbody.velocity.z, 0, walkDeaccelerationVolz, walkDeacceleration);
}
transform.rotation = Quaternion.Euler(0, cameraObject.GetComponent(MouseLook).currentYRotation, 0);
//New movement to remove latency in movement.
transform.position = Vector3(transform.position.x + Input.GetAxis("Horizontal") * walkAcceleration * Time.deltaTime, transform.position.y ,
transform.position.z + Input.GetAxis("Vertical") * walkAcceleration * Time.deltaTime);
//Old movement
//rigidbody.AddRelativeForce(Input.GetAxis("Horizontal") * walkAcceleration, 0, Input.GetAxis("Vertical") * walkAcceleration);
if (Input.GetButtonDown("Jump") && grounded)
rigidbody.AddForce(0, jumpVelocity, 0);
}
function OnCollisionStay (collision : Collision){
for(var contact : ContactPoint in collision.contacts) {
if(Vector3.Angle(contact.normal, Vector3.up) < maxSlope)
grounded = true;
}
}
function OnCollisionExit(){
grounded = false;
}
The issue is to do with (I'm sure):
transform.rotation = Quaternion.Euler(0, cameraObject.GetComponent(MouseLook).currentYRotation, 0);
However I'm not entirely sure how to modify this line in order to make it work with my modifications.
you want to rotate the camera, but I dont see setting the rotation anywhere. You just need to take Y Axis (I believe it's Y) from player's rotation and set it to Camera, ie. something like this (idk the syntax of UnityScript so here's C#):
Vector3 newRotation = cameraObject.transform.rotation;
newRotation.y = transform.rotation.y;
cameraObject.transform.rotation = newRotation;

Trouble with raycasting in Unity 3

I'm trying to script my AI on a simple way. The AI does a raycast in front, left and right of it. Then it takes a random direction in a way that doesn't contain a "Boundary"-element.
First, my Update() checks if it's time to calculate a new direction. If it is, it calculates the new direction, then it moves to that.
I'm using the following code to move:
Debug.DrawLine(transform.position, transform.position + transform.forward, Color.yellow);
Debug.DrawLine(transform.position, transform.position + transform.right, Color.yellow);
Debug.DrawLine(transform.position, transform.position - transform.right, Color.yellow);
//DEBUGS START AND END POSITION ARE CORRECT
var startTime;
if (Time.time > nextUpdate) {
Debug.Log("New check");
var dirWay = MoveDirection();
//if (dirWay == 0)
//rot = Quaternion.Euler(0, 0, 0);
if (dirWay == 1) {
rot = Quaternion.Euler(0, 90, 0);
}
if (dirWay == 2) {
rot = Quaternion.Euler(0, -90, 0);
}
if (dirWay == 3) { //backwards
rot = Quaternion.Euler(0, 180, 0);
}
nextUpdate = Time.time + walkTime; //for example, 2: Every 2 seconds an update
direction.y = 1;
direction.y = 1.5 - transform.position.y;
transform.rotation = transform.rotation * rot;
transform.position = transform.position + transform.forward + transform.forward;
//Plus 2 * transform.forward because it moves 2 places
}
The function MoveDirection checks for obstacles through raycasting. My AI moves the correct distance in the correct time, but walks through walls. That means my raycasting is wrong. I'm using the following code:
var obstacles = ["Border", "Boundary", "BoundaryFlame"];
var frontAvailable = true;
var leftAvailable = true;
var rightAvailable = true;
var hitFront: RaycastHit;
if (Physics.Raycast(transform.position, transform.position + transform.forward, hitFront, 1.9)) {
for (var i = 0; i < obstacles.length; i++)
{
if (hitFront.collider.gameObject.name.IndexOf(obstacles[i]) > -1)
{
frontAvailable = false;
}
}
}
var hitLeft: RaycastHit;
if (Physics.Raycast(transform.position, transform.position - transform.right, hitLeft, 1.9)) {
for (var j = 0; j < obstacles.length; j++)
{
if (hitLeft.collider.gameObject.name.IndexOf(obstacles[j]) > -1)
{
leftAvailable = false;
}
}
}
var hitRight: RaycastHit;
if (Physics.Raycast(transform.position, transform.position + transform.right, hitRight, 1.9)) {
for (var k = 0; k < obstacles.length; k++)
{
if (hitRight.collider.gameObject.name.IndexOf(obstacles[k]) > -1)
{
rightAvailable = false;
}
}
}
So, am I right that when I want to check 2 units in front of the AI (transform.forward from the AI's point of view, not the global view!), I should use: Physics.Raycast(transform.position, transform.position + transform.forward, hitFront, 1.9) ?
http://docs.unity3d.com/Documentation/ScriptReference/Physics.Raycast.html
So, am I right that when I want to check 2 units in front of the AI
(transform.forward from the AI's point of view, not the global view!),
I should use: Physics.Raycast(transform.position, transform.position +
transform.forward, hitFront, 1.9) ?
you should have Physics.Raycast(transform.position,transform.forward,hitFront, 1.9);