Trying to make my camera sit behind the character - unity3d

I'm trying to get my camera to sit behind my player. Currently, it follows the "tracker" which is a child object attached to the player but it doesn't follow relative to the character's rotation.
The camera rotates fine which just locks its view onto the tracker.
The offset is set manually in the script (inspector).
code:
private void cam_movement(GameObject tracker, bool tracking) {
transform.position = Vector3.Lerp(transform.position, tracker.transform.position + camera_offset, follow_speed * Time.deltaTime);
}
image
I removed the camera tracking's rotation code.

If the tracker gives the offset, why do you need another offset to the offset (camera_offset)? Or is the tracker the focus point that you aim the camera at?
Presumably, camera_offset is in world-space coordinates (given that you're adding it to .position), but you're probably thinking of it in object local-space coordinates.
Thus,
private void cam_movement(GameObject tracker, bool tracking) {
// convert offset from local- to world-space
var camera_worldOffset = tracker.transform.transformVector(camera_offset);
transform.position = Vector3.Lerp(transform.position, tracker.transform.position + camera_worldOffset, follow_speed * Time.deltaTime);
}

Why don't you use Cinemachine instead of the default camera? It's much easier

Related

Unity / Mirror - Is there a way to keep my camera independent from the player object's prefab after start?

I'm currently trying to create a multiplayer game using mirror!
So far I've been successful in creating a lobby and set up a simple character model with a player locomotion script I've taken and learnt inside out from Sebastian Graves on YouTube (you may know him as the dark souls III tutorial guy)
This player locomotion script uses unity's package 'Input System' and is also dependent on using the camera's .forward and .right directions to determine where the player moves and rotates instead of using forces on the rigidbody. This means you actually need the camera free in the scene and unparented from the player.
Here is my HandleRotation() function for rotating my character (not the camera's rotation function):
private void HandleRotation()
{
// target direction is the way we want our player to rotate and move // setting it to 0
Vector3 targetDirection = Vector3.zero;
targetDirection = cameraManager.cameraTransform.forward * inputHandler.verticalInput;
targetDirection += cameraManager.cameraTransform.right * inputHandler.horizontalInput;
targetDirection.Normalize();
targetDirection.y = 0;
if (targetDirection == Vector3.zero)
{
// keep our rotation facing the way we stopped
targetDirection = transform.forward;
}
// Quaternion's are used to calculate rotations
// Look towards our target direction
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
// Slerp = rotation between current rotation and target rotation by the speed you want to rotate * constant time regardless of framerates
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
transform.rotation = playerRotation;
}
It's also worth mentioning I'm not using cinemachine however I'm open to learning cinemachine as it may be beneficial in the future.
However, from what I've learnt and managed to find about mirror is that you have to parent the Main Camera under your player object's prefab so that when multiple people load in, multiple camera's are created. This has to happen on a Start() function or similar like OnStartLocalPlayer().
public override void OnStartLocalPlayer()
{
if (mainCam != null)
{
// configure and make camera a child of player
mainCam.orthographic = false;
mainCam.transform.SetParent(cameraPivotTransform);
mainCam.transform.localPosition = new Vector3(0f, 0f, -3f);
mainCam.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
cameraTransform = GetComponentInChildren<Camera>().transform;
defaultPosition = cameraTransform.localPosition.z;
}
}
But of course, that means that the camera is no longer independent to the player and so what ends up happening is the camera rotates when the player rotates.
E.g. if I'm in game and looking to the right of my player model and then press 'w' to walk in the direction the camera is facing, my camera will spin with the player keeping the same rotation while my player spins in order to try and walk in the direction the camera is facing.
What my question here would be: Is there a way to create a system using mirror that doesn't require the camera to be parented to the player object prefab on start, and INSTEAD works by keeping it independent in the scene?
(I understand that using forces on a rigidbody is another method of creating a player locomotion script however I would like to avoid that if possible)
If anybody can help that would be greatly appreciated, Thank You! =]
With the constraint of your camera being attached to the player you will have to adapt the camera logic. What you can do is instantiate a proxy transform for the camera and copy that transforms properties to your camera, globally, every frame. The parent constraint component might do this for you. Then do all your transformations on that proxy.
Camera script with instantiation:
Transform proxy;
void Start(){
proxy = (new GameObject()).transform;
}
void Update(){
//transformations on proxy
transform.position = proxy.position;
transform.rotation = proxy.rotation;
}

Get Unity compass true north heading

I'm currently trying to implement a location-based AR app for Android using Unity C# and ARCore. I have managed to implement an algorithm which gets latitude/longitude and translates it to unity meters. However, this is not enough to place objects at a GPS location since the orientation of the world will be off if you do not align the unity scene with the real world orientation.
Anyway, the problem with the compass is that I cannot find a way to align an object with the true north.
I have tried aligning an object with true north by using
transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
However this causes the object to constantly change rotation based on where my phone's heading so in a way true north is always changing.
What I am currently trying is:
var xrot = Mathf.Atan2(Input.acceleration.z, Input.acceleration.y);
var yzmag = Mathf.Sqrt(Mathf.Pow(Input.acceleration.y, 2) + Mathf.Pow(Input.acceleration.z, 2));
var zrot = Mathf.Atan2(Input.acceleration.x, yzmag);
xangle = xrot * (180 / Mathf.PI) + 90;
zangle = -zrot * (180 / Mathf.PI);
TheAllParent.transform.eulerAngles = new Vector3(xangle, 0, zangle - Input.compass.trueHeading);
This seems to be working better since the object will point towards a single direction with minimum shaking/jittering of the object due to erratic compass reading but points in one direction nonetheless. However, the problem with this is that it points to a different direction every time the app starts, so true north is never in one place according to the code. However the compass readings are fine as I have checked the readings against other GPS apps which implement a compass.
I have also tried transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0); but this gives the same always-changing result as the first one. Any help would be appreciated.
its how i solve this issue in my project
i wish it help you.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class newway : MonoBehaviour
{
GameObject cam;
void Start()
{
cam = Camera.main.gameObject;
Input.location.Start();
Input.compass.enabled = true;
}
void Update()
{
Quaternion cameraRotation = Quaternion.Euler(0, cam.transform.rotation.eulerAngles.y, 0);
Quaternion compass = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);
Quaternion north = Quaternion.Euler(0, cameraRotation.eulerAngles.y + compass.eulerAngles.y, 0);
transform.rotation = north;
}
}
Possibly, your GameObject is rotating on its own axes, but you need your GameObject to pivot around the camera, or the center.
If that's the case, try creating another empty GameObject, and set its position to (0, 0, 0), or wherever you wish the center to be. Then add original GameObject as a child to this new one.
Apply your transform.rotation script to this new GameObject.

Camera follow player issue (2d)

I am working on a 2D space game, similar to Roid Rage. I have a space shuttle in it. The shuttle will move around freely and will avoid obstacles. I have made the movement and rotation part of the shuttle successfully (using rigidbody2d). But now I am unable to make the camera follow the shuttle.
First I tried making the camera a child of shuttle. In this way, the camera followed the shuttle. But it didn't show any rotation of shuttle because I guess the camera also rotates with the shuttle in this case.
Then I did this:
public Transform shuttle;
private Vector3 offset;
void Start() {
offset = transform.position;
}
void LateUpdate() {
transform.position = shuttle.transform.position + offset;
}
In this case, the camera followed the shuttle but when I tap the screen and the shuttle is supposed to take a turn (in an orbit like path), it just rotates around its own axis.
Finally, I used this instead:
void LateUpdate() {
transform.position = Vector3.Lerp(transform.position, shuttle.position + offset, 0.125f);
}
Now, the result is that the shuttle is very shaky. Any solution to this problem?
Does something very simple like this not work? This is in the camera script, not attached to the GameObject.
public GameObject MyShuttle;
void LateUpdate() {
this.transform.position = MyShuttle.transform.position;
}
Found a solution after searching on forums. Since I was using Rigidbody2D to move the shuttle, I had to turn on its Interpolate property from None to Interpolate. The shaking was fixed by this.

Unity Mouselook from any Player Orientation

I am working on a first person game where the character is able to latch on to any flat surface and walk on it (kind of like moon boots). I am having issues with the camera since most implementations of mouse look I have been able to find depend on the player being oriented straight up and down in the world, so as soon as my "flipping" animation (the player orienting to the new surface) has finished, the camera will instantly flip back to straight up and down as defined by the world. What I need is a way to implement mouse look so that it does not reset the rotation after my animation. I am currently using:
transform.Rotate(-Input.getAxis("Mouse Y") turnSpeed Time.deltaTime, Input.getAxis("Mouse X") turnSpeed Time.deltaTime, 0);
in order to perform my mouse look rotations while avoiding the standard method, but this is clearly incorrect since I get some weird rotations when turning the camera horizontally. Is there a better way to implement mouse look so that it works correctly regardless of the orientation of the player?
You can plance camera inside player Transform and add this script to player:
public class MouseLook : MonoBehaviour {
[SerializeField]
Camera Camera;
[Range(10f,50f)]
public float Speed = 30;
void Update () {
transform.rotation = Quaternion.AngleAxis(Input.GetAxis("Mouse X") * speed * Time.deltaTime, transform.rotation * Vector3.up)*transform.rotation;
Camera.transform.rotation = Quaternion.AngleAxis(-Input.GetAxis("Mouse Y") * Speed * Time.deltaTime, Camera.transform.rotation * Vector3.right)* Camera.transform.rotation;
}
}
You add reference to Camera in inspector. You will have to check not to rotate above +/- 90 degrees on camera to avoid over rotating to back. If you will have issue with that I will help you.

Unity Navmeshagent won't face the target object when reaches stopping distance

I'm trying to get the NPC to look at the main character when I'm talking to him. I need to make sure it looks natural and that he is facing me. I know I can do Transform.LookAt() but that is too instant and unnatural.
How do I rotate the navmeshagent to face my character when its stopped moving?
Try this out to control the body orientation - the slerp is adjustable to your desired rotation speed (https://docs.unity3d.com/ScriptReference/Quaternion.Slerp.html):
private void FaceTarget(Vector3 destination)
{
Vector3 lookPos = destination - transform.position;
lookPos.y = 0;
Quaternion rotation = Quaternion.LookRotation(lookPos);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, [fill in desired rotation speed]);
}
if(agent.remainingDistance < agent.stoppingDistance)
{
agent.updateRotation = false;
//insert your rotation code here
}
else {
agent.updateRotation = true;
}
This will rotate your agent when it's distance below the stoppingDistance variable. However it will look inhuman, so if you're going for a humanoid ai I'd recommend looking at the unity Mecanim demo (particularly the locomotion scene) as it has code and animations that will properly animate the agent.
Maybe try this Head Look Controller. It's very smooth and blends with animations!
Put the char in a game object and copy the navmesh from the char to the parent, uncheck enable in char. move any scripts up too.
Just spent 5 hours to find this.