I am trying to create a 3rd person movement script using Cinemachine as camera, I followed Brackeys "THIRD PERSON MOVEMENT in Unity" YouTube tutorial. I then Changed the base of it from character controller to rigidbody and the movement works perfectly fine. However my code sets the velocity of the rigidbody's y axis to 0 when I move the player which fights the gravity making the player jitter slowly to the ground when I move. The Character however does drop to the ground when the player stops moving. All I need is for the script to ignore the y axis and simply listen to unity's gravity.
void Update()
{
if (!photonView.isMine)
{
Destroy(GetComponentInChildren<Camera>().gameObject);
Destroy(GetComponentInChildren<Cinemachine.CinemachineFreeLook>().gameObject);
return;
}
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
isGrounded = Physics.CheckSphere(new Vector3(transform.position.x, transform.position.y - 1, transform.position.z), 0.01f, layerMask);
Vector3 inputVector = new Vector3(horizontal, 0f, vertical).normalized;
if (inputVector.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(inputVector.x, inputVector.z) * Mathf.Rad2Deg + cam.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
rb.velocity = moveDir.normalized * speed;
}
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce);
}
}
The player jitters because, in your movement section, you set the y velocity to 0, since Vector3.forward returns new Vector3(0, 0, 1) and you only rotate the vector around the y axis. Instead of this, consider doing:
Vector3 moveDir = new Vector3(transform.forward.x, rb.velocity.y, transform.forward.z);
This will preserve the velocity as it was, removing the jittering.
Note: transform.forward automatically gets the forward vector for the player.
Related
I would like to have a Gameobject point to another only on the Local X-axis.
void FixedUpdate()
{
if(started){
Vector3 targetPosition = target.position;
Vector3 direction = Vector3.ProjectOnPlane(targetPosition - transform.position, transform.right);
Quaternion lookRot = Quaternion.LookRotation(direction, transform.right);
transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRot, Time.fixedDeltaTime * 45);
}
On the y-axis it worked with transform.up instead of transform.right, but on the x-axis the Gameobject only rotates permanently around the z-axis.
You could do something like this:
Vector3 beforeRot = transform.eulerAngles;
transform.LookAt(gameObjectToLookAt.transform);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, beforeRot.y, beforeRot.z);
This will take a record of the position before looking at the object.
Make it look at the object.
Reset rotation back to its original except the X rotation
I have been experimenting with trying to recreate a 3rd person character controller from a Brackeys tutorial, but using the new input system and rigid body physics.
The rotation works properly, but moving forward or back moves me forward compared to the camera, and moving left or right moves me backward.
The desired effect is changing the input should change my rotation to match the input direction relative to the camera and then move in the direction the player model is facing
Here is where I'm at:
private Vector3 GetMoveInput()
{
return new Vector3(_input.MoveInput.x, 0f, _input.MoveInput.y); //convert input Vector2 into a Vector3
}
private void PlayerMove()
{
if (_playerMoveInput.magnitude > 0.01f){ //only update rotation if player is moving
float targetAngle = Mathf.Atan2(_playerMoveInput.x, _playerMoveInput.z) * Mathf.Rad2Deg + _mainCamera.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
//down here is where the problem lies I believe
_playerMoveInput = new Vector3(_playerMoveInput.x * _movementMultiplier * _rigidBody.mass,
_playerMoveInput.y,
_playerMoveInput.z * _movementMultiplier * _rigidBody.mass);
_rigidBody.AddRelativeForce(_playerMoveInput, ForceMode.Force);
}
}
I have tried setting y and z to 0f, multiplying by transform.forward, setting _playerMoveInput to transform.forward, and Quaternion.Euler(0f, angle, 0f) * transform.forward but no positive results.
i have start a project in unity 3d.I want to make a spaceship that moving forward,but when i pressed the ArrowUp then i want to change its y postion to
( currentpos+ 1.5 ) but i want this smoothly.
this is my code
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey (KeyCode.UpArrow))
transform.position = new Vector3 (transform.position.x, 5f,
transform.position.z);
through the above code the Y position of object can b changed but it work so fast and i want to make it smooth.
so please help me.
I think the best solution to your problem is to use Mathf.SmoothDamp.
Example:
private float targetY = 0f;
private float verticalVelocity = 0f;
private const float smoothTime = 1f;
private void Update()
{
transform.position += transform.forward * Time.deltaTime * 10f;
if (Input.GetKey(KeyCode.UpArrow))
{
targetY = 5f;
}
float y = Mathf.SmoothDamp(transform.position.y, targetY, ref verticalVelocity, smoothTime);
transform.position = new Vector3 (transform.position.x, y, transform.position.z);
}
This example will smoothly change the y coordinate to 5 over the course of 1 second (you can change the smoothTime constant for a different time).
Based in your own code the easiest way for you to work it out could be something like this
//this sets the X position
transform.position += transform.forward * Time.deltaTime * 10f;
//if the button is pressed then modify Y
if (Input.GetKey (KeyCode.UpArrow))
transform.position += new Vector3 (0, 5f * Time.deltaTime * y_speed,0);
y_speed could be a public float y_speed = 1.0f in your script so you could modify it from the inspector to get the effect you want to achieve.
Hope it helps!
Assuming your spaceship is a rigidbody, you should take a look at Rigidbody.AddForce
https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
By working with forces, you can get a smooth movement in all directions very easily, and tweak it within the Rigidbody's parameters (like mass) without fiddling in the script again. It's part of the Unity physics model.
If you only want to move in y-direction, input a vector like (0,1,0) but you can also input the Transform.forward vector of your spaceship's Gameobject. That way, it will always move the direction it is facing in.
I'm struggling with false Gravity in a Cylinder or Capsule. Basically I thought I could take the same Code as for spherical gravity, which does not work. So I changed some lines to get a better result.
[SerializeField] float gravity = 10;
public void Attract ( Transform target )
{
Vector3 gravityUp = (target.position - new Vector3(transform.position.x, transform.position.y,target.position.z)).normalized;
Vector3 bodyDown = -target.up;
Rigidbody rb = target.GetComponent<Rigidbody>();
rb.AddForce(gravityUp * gravity);
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
}
This worked OK on the first try. But the Player(target) can't rotate one the Y-Axis. Does anyone have any ideas?
OK, I tried the following.
Quaternion targetRotation = Quaternion.FromToRotation(bodyDown, gravityUp) * target.rotation;
targetRotation.x = 0;
target.rotation = Quaternion.Slerp(target.rotation, targetRotation, 30.0f * Time.deltaTime);
Now I use the Surface normal to rotate the Player.
if (Physics.Raycast(attractedBody.transform.position + attractedBody.transform.forward, -attractedBody.transform.up, out hit, distance))
{
surfaceNorm = hit.normal;
}
But without Rigidbody Contrains the Player starts rotating without any Input. So I have to use:
rb.constraints = RigidbodyConstraints.FreezeRotation;
This works.
Hello I'm having trouble with calculating the rotation of my characters arm to account for the guns offset from the shoulder pivot to aim the muzzle of the gun at the mouse. But when it rotates the arms it also has to update the new weapon offsets causing the guns rotation to jitter if the mouse position + weapon offset is closer then the muzzle of the gun.
public void rotateArm(){
Vector3 centerPosition = armPivotPos.position;
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition)+updatedWeaponOffset();
mousePosition.z = armPivotPos.position.z;
Vector3 dir = centerPosition - mousePosition;
float angle = Mathf.Atan2(dir.y, dir.x) * -Mathf.Rad2Deg;
Quaternion temp = Quaternion.AngleAxis(angle, -Vector3.forward);
armPivotPos.eulerAngles = new Vector3(temp.eulerAngles.x, temp.eulerAngles.y, temp.eulerAngles.z);
}
public vector3 updatedWeaponOffset(){
Vector3 weaponOffset = armPivotPos.position - muzzlePos.position;
return weaponOffset;
}