I have a cube that spins all over the place when I hit an object.(the camera and character spins) UNITY - c#

I have a simple movement that relvolves around moving foward depending on where I look. The camera is made to follow the player. The problem I am havaing is that whenever I hit an object, my character(along with the camera) start spinning crazily all over the place. (I am new to coding)
Here is the code to the movement of where my character is facing :
public class Player : MonoBehaviour {
public float movementSpeed = 10;
public float turningSpeed = 60;
public Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody> ();
}
void Update() {
float horizontal = Input.GetAxis("Mouse X") * turningSpeed *
Time.deltaTime;
transform.Rotate(0, horizontal,0);
float vertical = Input.GetAxis("Mouse Y")* turningSpeed * Time.deltaTime;
transform.Rotate(vertical, 0, 0);
float movement = Input.GetAxis("Foward") * movementSpeed *
Time.deltaTime;
transform.Translate(0, 0,movement);
}
}
(Sorry for bad format)
The Mouse X just makes it so that it rotates on the x axis of mouse(same with y axis). The Foward is just the vertical input preset in unity.
Here is the code to the lookAt player :
public class LookAtCamera : MonoBehaviour {
public GameObject target;
void LateUpdate() {
transform.LookAt(target.transform);
}
}

Answer
I believe your rigidbody is being more heavily affected than what you desire by the bounce force occuring as you hit the object.
Possible solutions
Depending on which collider type acts as your legs, the weight of the objects involved, what behaviour you intend and more the solution can vary.
Possible solution 1:
One option is to freeze the rotation of your object on it's Rigidbody component, you can decide which axes to freeze rotation on. If freezed they can't be pushed by outside forces.
Possible solution 2:
If you wish the player to only be affected by your script you can set the rigidbody kinematic, meaning that it only is affected by scripts and animation. This is a contrast to being set to dynamic where other objects can affect it.
Possible solution 3:
Play around with the angular drag and mass of the rigidbody to slow down rotation.

Related

How to make the main camera rotate with the player?

I have the following script which should make the main camera follow and rotate with the player's movements.
public class FollowPlayer : MonoBehaviour
{
[SerializeField]
float mouseSensitivity;
public Vector3 cameraOffset;
public Transform Player;
public Transform mainCamera;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
cameraOffset = transform.position - Player.transform.position;
}
void Update()
{
Rotate();
}
private void Rotate()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
Player.Rotate(Vector3.up, mouseX);
mainCamera.Rotate(Vector3.up, mouseX); //shows abnormal rotation (hides the player as well)
}
private void LateUpdate()
{
Vector3 newPosition = Player.position + cameraOffset;
transform.position = newPosition;
}
}
The camera follows the player, however, but it does not rotate with the player's rotations. Please note that making the main camera the child of the player is not an option here, since I have to use this script on multiplayer. I want the mouse to be able to rotate both the main camera and the player at the same time.
The reason the camera is not rotating, is that you capture the initial offset on start, which is expressed in absolute (world space) position. This can be easily fixed using transform.TransformPoint method. What you then need to do is address camera rotation. In the simplest case you can just use 'LookAt' method
private void LateUpdate()
{
Vector3 newPosition = Player.position + Player.TransformPoint(cameraOffset);
mainCamera.position = newPosition;
mainCamera.LookAt(Player.position, Vector3.up);
}
I also noticed that you use transform.position (a transform from the object your script is attached to) but then you also use mainCamera transform as a seperate transform, mixing it like that might lead to confusion later. You should either always access the camera via mainCamera reference, or you could always keep the script attached to the camera and use transform reference.
I also noticed that you use one script to do two seperate things, it controls both player rotation and camera position/rotation while following the player. While there is nothing stoping you from doing that, its often a good idea to split it into doing two things each doing one logical thing

Rigidbody2D.MovePosition cause lags in physic, for example, gravity

I tested and this script cause lags in physic. It seems to me that it call physic not per 0,2 seconds, but much-much more rarely and because of this object falling much more slower.
Here's a gif to demonstrate what happens: The purple one without script, the blue one with script.
So how can I fix that?
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb;
Vector2 movement = new Vector2(0, 0);
public float movementSpeed = 10f;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
movement = new Vector2(Input.GetAxisRaw("Horizontal"), 0);
}
void FixedUpdate()
{
rb.MovePosition(rb.position + movement * movementSpeed * Time.fixedDeltaTime);
}
}
As said MovePosition overrules the movement => don't use it if you want physics (force) based movements and reaction to collisions etc.
You want to use the input only for the horizontal movement but use physics for the vertical. MovePosition affects both directions.
Try directly setting the Rigidbody.velocity instead
private void Update()
{
// Get the current velocity
var velocity = rb.velocity;
// Only overwrite the x velocity
// since the velocity is only applied in the FixedUpdate anyway
// there is no problem setting this already in Update
// And since it is the velocity which is already frame-rate independent
// there is no need for Time.deltaTime
velocity.x = Input.GetAxisRaw("Horizontal") * movementSpeed;
// Assign back the changed velocity
rb.velocity = velocity;
}
There is an issue with the logic of your code if I understand what you want to do.
You seem to be moving in a vertical fashion yet only have the x component of your vector2 from the horizontal input.
new Vector2(Input.GetAxisRaw("Horizontal"), 0);
If the GIF you attached, the object is just in freefall, so that would be a vertical drop, or the y component of the vector2, which you are setting to 0. Think of this as (x,y) or (move horizontally (left/right), move vertically (up/down)).
I would change the above line to:
movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
You can now move vertically using vertical input. Something else which would not cause your issue, but is mentioned on the MovePosition docs is to mark your Rigidbody2D as Interpolate. It is the bottom field in the Rigidbody2D component labeled Interpolate, set it from None to Interpolate.
The reason your object is moving slowly without any input is because you still have your Gravity Scale on the Rigidbody set to 1 instead of 0. If you are trying to simulate gravity with this script, add the vertical component to your input vector and set the Gravity Scale field on the Rigidbody to 0. The MovePosition is fighting the current gravity attempting to affect it.

transform.lookat behaving weirdly OR I am missing something (unity3d c#)

I am trying to instantiate a prefab, a fireball, from a baddie, and at the time of instantiation pass the current player position to the fireball and use this to target the fireball at the player. The fireball translates/moves forward on its transform.forward vector. Thus the fireball should head from the baddie towards the player's position at the time the fireball was created.
What I am finding is that the direction is being set (via the transform.lookat() function on the fireball), but it is almost always the wrong direction. It is not 90 or 180 off. How much it is off by depends on where the player is in respect to the baddie. The pattern is symmetrical around the z axis.
Assuming the baddie is at (0,0,0):
when the player is at (0,0,10) the fireballs head directly towards the player
when the player is at (0,0,-10) the fireballs head away from the player (180 degrees. The exact opposite direction. The same direction as when the player was at (0,0,10))
when the player is at (10,0,0) the fireballs head 90 degrees away from the player (to the players right if facing the baddie)
when the player is at (-10,0,0) the fireballs head 90 degrees away from the player (to the players left if facing the baddie)
These values move smoothly as the player moves through these angles. It only ever hits the player in one direction.
I have tried the following (some of these were probably not required):
re-import all assets
create new project on a new machine to reproduce the issue.
I've tried setting the lookat variable to be:
player transform
the vector 3 world coordinate of the player (this is what is in the code below)
player.transform.position - baddie.transform.position
baddie.transform.position - player.transform.position
These all yield the same results.
Here is my code.
Code to Instantiate the fireball from the baddie.
public class Baddie : MonoBehaviour {
public GameObject fireballPrefab;
public GameObject playerGameObject;
public float countDownForFireball;
private float currentCountDownForFireball;
void Start () {
playerGameObject = GameObject.FindGameObjectWithTag("Player");
currentCountDownForFireball = 0;
}
void Update () {
if(currentCountDownForFireball <= 0)
{
GameObject newFireball = GameObject.Instantiate(fireballPrefab, transform.position, Quaternion.identity);
newFireball.GetComponent<Fireball>().SetTarget(playerGameObject.transform.position);
currentCountDownForFireball = countDownForFireball;
}
else
{
currentCountDownForFireball -= Time.deltaTime;
}
}
}
Code on the fireball
public class Fireball : MonoBehaviour {
private float moveSpeed;
private Vector3 target;
// Use this for initialization
void Start () {
moveSpeed = 15f;
}
// Update is called once per frame
void Update (){
transform.Translate(transform.forward * Time.deltaTime * moveSpeed);
}
public void SetTarget(Vector3 newTarget){
target = newTarget;
transform.LookAt(target);
}
}
The error is in the usage of Transform.Translate. Its secondary parameter is a Space argument that defaults to Space.Self. You want the space of your direction to match the space you're translating in so you want to pass in Space.World:
// transform.forward is the transform's forward vector in "world space"
transform.Translate(transform.forward * Time.deltaTime * moveSpeed, Space.World);
Alternatively, you can keep using the default Space.Self with Vector3.forward instead of transform.forward:
// Vector3.forward is (0,0,1). In "self space" this is "forward"
transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed); // Space.Self

Camera shaking on rotating player while crouching in unity

I am having a problem with the camera following the player. When the player moves, the camera shakes and this effect is more noticeable when the player is in the crouched position. I am using root motion for the player with animations by mixamo.
Player Script:
Transform cameraT;
void Start () {
cameraT = Camera.main.transform;
}
void FixedUpdate ()
{
float sideMotion = Input.GetAxis("SideMotion");
float straightMotion= Input.GetAxis("StraightMotion");
if (Mathf.Abs(sideMotion) > 0 || Mathf.Abs(straightMotion) > 0)
{
transform.eulerAngles = new Vector3(transform.eulerAngles.x,
cameraT.eulerAngles.y);
}
}
Camera Script:
public float distanceFromPlayer=2f;
public float mouseSensitivity=6;
public Transform player;
public Vector2 pitchConstraint= new Vector2(-30,80);
Vector3 rotationSmoothVelocity;
Vector3 currentRotation;
public float rotationSmoothTime = 0.2f;
float yaw; //Rotation around the vertical axis is called yaw
float pitch; //Rotation around the side-to-side axis is called pitch
private void LateUpdate()
{
yaw += Input.GetAxis("Mouse X") * mouseSensitivity;
pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
pitch = Mathf.Clamp(pitch, pitchConstraint.x, pitchConstraint.y);
currentRotation = Vector3.SmoothDamp
(currentRotation, new Vector3(pitch, yaw), ref rotationSmoothVelocity, rotationSmoothTime);
transform.eulerAngles = currentRotation;
transform.position = player.position - transform.forward * distanceFromPlayer;
}
For public transform I just added an empty game object to player chest level and parented it to the player. I got the rotating camera smoothly trick from an online tutorial but that exact thing won't work on player rotation though.
A character controller is attached to player without any rigidbody or collider.
You are going to want to use Lerp on the camera in order to smooth its motion from one position to another. The Scripting API has a good example of Vector3.Lerp.
So in your case, you could add a public variable for smoothing position as well. Something like positionSmoothTime. Then make a "Desired Position" variable, we'll call it destPosition.
Vector3 destPosition = player.position - transform.forward * distanceFromPlayer;
transform.position = Vector3.Lerp(transform.position, destPosition, positionSmoothTime);
This should effectively smooth it to where the stuttering should go away. Another thing that will help that someone else mentioned is using a part of the body that moves less (Like the head) as the target. This combined with the Lerp function will give you a smooth camera movement.
Another large help would be to move things into the Update() function. The reason being is FixedUpdate() doesn't get called every frame. So you could potentially get stutter as a result. If you move everything into Update() it will update every frame and help smooth things out. If you do this though you will need to multiply all movement by Time.deltaTime as shown in the example below.
Vector3 destPosition = (player.position - transform.forward * distanceFromPlayer) * Time.deltaTime;
For more examples, check the links to each function to see Unity's documentation on it. It has examples of everything I've shown here.

Unity3D C#. Using the transform.RotateAround() function while keep the distance between two objects constant

I am trying to practice making third person controllers in Unity 3D. I am a beginner, and I am completely baffled on how to make my controller functional. I have been doing hours of research, but no thread I can find seem to answer my question. I have two scripts, a CameraController, and a CharacterController. My code is below.
CameraController:
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject target;
public float rotationSpeed;
Vector3 offset;
Vector3 CameraDestination;
// Use this for initialization
void Start () {
offset = transform.position - target.transform.position;
CameraDestination = offset + transform.position;
rotationSpeed = 50f;
transform.position = CameraDestination;
}
// Update is called once per frame
void Update () {
transform.LookAt (target.transform.position);
float h = Input.GetAxisRaw ("Horizontal");
transform.RotateAround (target.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
target.transform.Rotate (0f, Time.deltaTime * h * rotationSpeed, 0f);
}
}
CharacterController:
using UnityEngine;
using System.Collections;
public class CharController : MonoBehaviour {
public float playerSpeed = 10f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
float Vertical = Input.GetAxis("Vertical");
transform.position += transform.forward * Time.deltaTime * playerSpeed * Vertical;
}
}
When either the left or right arrow key is pressed, both the player and the camera rotates. If I try to attach the camera to the player as a children, the camera's rotation becomes messed up, but if I do not attach the camera to the player, the camera stops following the player. If I try to set the camera to a specific position relative to the player, it stops revolving around the player like it is intended to do. I simply can not come up with a method that works.Thank you for answering my question in advance!
When I go about this, I like to have an empty gameObject which has 2 children, the camera and then the mesh of the character.
> CharacterController
> Camera
> CharacterRig
When you want to rotate the character, rotate the CharacterController, then when you want to rotate the Camera around the character, change your code to:
transform.RotateAround (CharacterRig.transform.position, Vector3.up, Time.deltaTime * h * rotationSpeed);
This will allow your camera to rotate irrespective of any character animation and should solve your issue. This is very important if you want to implement animations later, as you don't want to parent the camera to the thing that is being animated because it will move with the animation.
P.s. Your code appears fine. Certain that it is purely the way you have set up the game objects.

Categories

Resources