Unity Smooth 2D Camera following - Huge Issue :( - unity3d

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);
}
}

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.

Unity - Vector3.Lerp / MoveTowards doesn't work

The problem I can't solve is: cloned object, slow progression of parent object to X axis. But no matter what I did I could do it based on time, this is the latest version of the code.
public GameObject Ball;
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Gate"))
{
GameObject clone2 = Instantiate(Ball, transform.position, transform.rotation);
transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x * 2,
transform.position.y,
transform.position.z), 25);
clone2.transform.parent = gameObject.transform;
}
if (other.CompareTag("Push"))
{
Destroy(gameObject);
}
}
#BugFinder already mentioned it in the comments. But the likely issue is that OnTriggerExit only gets called once and moves only one frame. Not only that but you are moving it over 25 seconds. Which is a long time for a Lerp function.
Below is a solution you can try:
float speed = 5;
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Gate"))
{
GameObject clone2 = Instantiate(Ball, transform.position, transform.rotation);
Vector3 targetLocation = new Vector3(transform.position.x * 2, transform.position.y, transform.position.z);
StartCoroutine(MoveTowardsLocation(clone2.transform, targetLocation, speed));
}
else if (other.CompareTag("Push"))
{
Destroy(gameObject);
}
}
private IEnumerator MoveTowardsLocation(Transform movedObj, Vector3 targetLocation, float speed)
{
Vector3 direction = (movedObj - movedObj.position).normalized;
while(Vector3.Distance(movedObj.position, targetLocation) > 0.01f)
{
movedObj.position = Vector3.Lerp(movedObj.position, movedObj.position + direction * speed * Time.deltatime, 1f);
yield return null;
}
movedObj.position = targetLocation;
}
In your code Lerp is called only once on trigger exit and position is updated only in one frame which is not resulting to visible change. To fix it you need start a coroutine on trigger exit and change transform.position in coroutine.

Throttle movement in the cockpit

void HandleMouse()
{
if(Input.GetMouseButton(0))
{
if(isTouching)
{
HandleDragging();
}
}
else
{
isTouching = false;
ResetKnob();
}
}
void HandleTouches()
{
}
protected virtual void HandleDragging()
{
//Get the target position for the knob
Vector2 wantedPosition = Vector2.zero;
RectTransformUtility.ScreenPointToLocalPointInRectangle(bounds, Input.mousePosition, null, out wantedPosition);
knob.anchoredPosition = Vector2.Lerp(knob.anchoredPosition, wantedPosition, Time.deltaTime * dragSpeed);
//Find the normalized Delta for the Knob
float xDelta = knob.anchoredPosition.x / (bounds.rect.width * 0.5f);
float yDelta = knob.anchoredPosition.y / (bounds.rect.height * 0.5f);
finalDelta = new Vector2(xDelta, yDelta);
finalDelta = Vector2.ClampMagnitude(finalDelta, 1f);
}
void ResetKnob()
{
knob.anchoredPosition = Vector2.Lerp(knob.anchoredPosition, Vector2.zero, Time.deltaTime * resetSpeed);
finalDelta = Vector2.zero;
}
I am trying to move a throttle up and down in the 3d space .I am using a 3d throttle object in side the cockpit to move up and down using mouse point i tried for moving the 2d sprite using above code it works fine but not working for moving a 3d throttle object.
spri
Mathf.Lerp(inputvalue, -10f, 10f);
I think your error is you are trying to interpolate your input to 10, when the Lerp function can only interpolate [0,1], Mathf.Lerp
You need to call it as Mathf.Lerp(-10, 10, inputValue);
Once you get the interpolation value just add that to the translation
var value = Mathf.Lerp(-10, 10, inputValue);
transform.position += Vector3.forward * value;
Find out how far your throttle is:
Vector2 throttleDownPosition = Vector2.zero; // Or whatever it is. I can't tell from your code.
Vector2 throttleUpPosition = new Vector2(0f,1f); // Or whatever it is. I can't tell from your code.
Vector2 throttleCurrentPosition = knob.anchoredPosition;
// Calculate ratio between current throttle / full throttle
float throttlePercentage =
Vector2.Distance(throttleCurrentPosition, throttleDownPosition)
/ Vector2.Distance(throttleUpPosition, throttleDownPosition);
Then, using what position and rotation your 3D throttle object should be when throttle is at 0%:
Vector3 startPosition
Quaternion startRotation
as well as the position and rotation your 3D throttle object should be when throttle is at 100%:
Vector3 endPosition
Quaternion endRotation
you can use Vector3.Lerp and Quaternion.Lerp to find the appropriate position and rotation for the current throttle setting:
Vector3 lerpedPosition = Vector3.Lerp(startPosition, endPosition, throttlePercentage);
Quaternion lerpedRotation = Quaternion.Lerp(startRotation, endRotation, throttlePercentage);
throttleObject.transform.position = lerpedPosition;
throttleObject.transform.rotation = lerpedRotation

Why my code fires bullet at random positions?

I see that the bullets are being fired at random positions and not actually in forward direction of the camera. What's wrong here and how should I fix it?
So I am using pooling and each time the bullet is enabled this code is run:
private void OnEnable()
{
transform.position = Camera.main.transform.position;
transform.rotation =Quaternion.identity;
GetComponent<Rigidbody>().AddForce((Camera.main.transform.forward + new Vector3(0, 0, 0)) * 5000);
Invoke("Destroy", 1.5f);
}
I have also changed it to the below code but even the second one doesn't work.
private void OnEnable()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.position = Camera.main.transform.position;
rb.rotation = Quaternion.identity;
rb.AddForce((Camera.main.transform.forward + new Vector3(0, 0, 0)) * 5000);
Invoke("Destroy", 1.5f);
}
First of all make sure the code works with out pooling. Secondly disable the collider component on the bullet (they might be colliding with themselves).
I've quickly tried this on my machine and this is the result I get.
using UnityEngine;
public class BulletController : MonoBehaviour
{
[SerializeField]
GameObject bulletPrefab;
void Update()
{
GameObject bullet = Object.Instantiate(bulletPrefab);
Rigidbody body = bullet.GetComponent<Rigidbody>();
body.position = Camera.main.transform.position;
body.AddForce(Camera.main.transform.forward * 75f, ForceMode.Impulse);
}
}
Here is the code I use with direction, position and velocity variables.
void Inception::shootGeode(std::string typeGeode, const btVector3& direction) {
logStderr(VERBOSE, "MESSAGE: Shooting geode(s)...\n");
std::shared_ptr<Geode> geode;
glm::vec3 cameraPosition = m_camera->getPosition();
btVector3 position = glm2bullet(cameraPosition + 3.0f * glm::normalize(m_camera->getTarget() - cameraPosition));
if (typeGeode == "cube")
geode = m_objectFactory->createCube("cube", new btBoxShape(btVector3(1.0f, 1.0f, 1.0f)), position, "dice");
if (typeGeode == "sphere")
geode = m_objectFactory->createSphere("sphere", new btBoxShape(btVector3(1.0f, 1.0f, 1.0f)), position);
btVector3 velocity = direction;
velocity.normalize();
velocity *= 25.0f;
geode->getRigidBody()->setLinearVelocity(velocity);
}

object movement as wave in Unity 3d

I created a object in unity
GameObject monsterclone =
(GameObject)Instantiate(monsterPrefab, floorPosition, Quaternion.identity);
This object should move in a wave style from a limit1 to limit2.
Then move back from limit2 to limit1.
Y position as well x position have to change in a specific way.
Vector3 nPos = mfloorPos + new Vector3(2f, 0f, 0f);
Vector3 oPos = mfloorPos + new Vector3(-2f, 0f, 0f);
How can I do it?
I can't exactly write the code without knowing more specific but i think this question is already asked any this link will help you out MOVE OBJECT as wave
EDIT:
I think the flat up and float down functionality will work for you for moving one point to another
example:
var floatup;
function Start(){
floatup = false;
}
function Update(){
if(floatup)
floatingup();
else if(!floatup)
floatingdown();
}
function floatingup(){
transform.position.y += 0.3 * Time.deltaTime;
yield WaitForSeconds(1);
floatup = false;
}
function floatingdown(){
transform.position.y -= 0.3 * Time.deltaTime;;
yield WaitForSeconds(1);
floatup = true;
}
example taken from
float amplitudeX = -25.0f;
float amplitudeY = 5.0f;
float omegaX = 0.5f;
float omegaY = 4.0f;
float index;
void Update () {
index += Time.deltaTime;
float x = amplitudeX*Mathf.Cos (omegaX*index);
float y = Mathf.Abs (amplitudeY*Mathf.Sin (omegaY*index));
if(transform.position.x > 24){
transform.eulerAngles = new Vector3(270, -90, 0);
}
if(transform.position.x < -24){
transform.eulerAngles = new Vector3(270, 90, 0);
}
transform.localPosition= new Vector3(x,y,20);
}
If this is a consitant wave and not dependant on speed I would use an animation to create a literal wave curve of the Position.Y value (much in the same principle as Ravindra Shekhawat has explained.) you can find out more about animation here.
Here is some code (untested) that you could go off. It is in c# so I hope it proves no issue with putting in to JavaScript.
bool monsterMoving = false;
void Update(){
//check monster moving to start updating position
if(monsterMoving == true){
//moving animation controls up and down "wave" movement
animation.CrossFade('moving');
//Lerp changes position
Transform.Lerp(transform.Position, oPos, Time.deltaTime);
if (transform.Position == oPos) {
//We are at destination, stop movement
monsterMoving = false;
}
} else {
// if monster stopped moving, return to idle animation (staying still)
animation.CrossFade('idle');
}
}
// function to send a new position to the monster object
void MoveTo(Vector3 newPos){
oPos = newPos;
monsterMoving = true;
}