How to rotate object slowly in this situation in unity? - unity3d

I am creating a building system in unity and when a key is pressed this function is run.
In this function I want to rotate the buildModel 90 degrees slowly over time.
Here is the function and what I tried:
public void RotateBuild()
{
//buildModel.transform.Rotate(0, 0, 90.0f);
Vector3 newDirection = Vector3.RotateTowards(buildModel.transform.eulerAngles, buildModel.transform.localEulerAngles + new Vector3(0, 90, 0), Time.fixedDeltaTime, 0);
buildModel.transform.rotation = Quaternion.LookRotation(newDirection);
}
I want to rotate it on the y axis, just like in Fortnite.
Unfortunately, it doesn't work now, so does anyone know a solution?

private float _rotationSpeed = 180f;
private Quaternion _targetRotation;
void Start(){
_targetRotation = buildModel.transform.rotation;
}
public void RotateBuilding(){
_targetRotation = buildModel.transform.rotation * Quaternion.AngleAxis(90f, Vector3.up);
}
public void Update(){
buildModel.transform.rotation = Quaternion.RotateTowards(buildModel.transform.rotation, _targetRotation, Time.deltaTime * _rotationSpeed);
}

Related

Why is my Controller drifting with Slerp?

I've been working on this Controller, where I walk around a small planet. I'm using Quaternion.Slerp, and when I'm at certain points on the planet, the controller slowly drifts, rotating around the Y axis. My thought is that it is holding a value based on my starting position, and so when I move to different points, the Slerp function is trying to spin me toward that location? I've tried messing around with the script, moving different portions to their own custom methods to pinpoint the issue, but I'm a bit lost at this point. Any help would be appreciated!
I think the issue is going to be somewhere in the bottom two methods NewRotation, or RunWalkStand.
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private LayerMask _groundMask;
[SerializeField] private Transform _groundCheck;
[SerializeField] private Transform cam;
public float jumpCooldown = 1f;
public float groundCheckRadius = 0.3f;
private float speed = 8;
private float runSpeed = 2;
private float turnSpeed = 800f;
private float jumpForce = 500f;
private Rigidbody rb;
private Vector3 direction;
private GravityBody _gravityBody;
private Animator playerAnimator;
private GameObject planetRecall;
void Start()
{
_gravityBody = transform.GetComponent<GravityBody>();
playerAnimator = GetComponent<Animator>();
planetRecall = GameObject.FindGameObjectWithTag("Planet Recall");
}
void Update()
{
bool isCloseToGround = Physics.CheckSphere(_groundCheck.position, groundCheckRadius, _groundMask);
NewRotation();
if (Input.GetKeyDown(KeyCode.Space) && isCloseToGround)
{
Jump();
}
}
void FixedUpdate()
{
RunWalkStand();
}
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject == planetRecall)
{
playerAnimator.SetBool("Grounded", true);
}
}
private void Jump()
{
rb.AddForce(-_gravityBody.GravityDirection * jumpForce, ForceMode.Impulse);
playerAnimator.SetTrigger("Fly_trig");
playerAnimator.SetBool("Grounded", false);
}
private void NewRotation()
{
rb = transform.GetComponent<Rigidbody>();
Vector3 mouseRotationY = new Vector3(0f, Input.GetAxisRaw("Mouse X"), 0f);
Quaternion rightDirection = Quaternion.Euler(0f, mouseRotationY.y * (turnSpeed * Time.deltaTime), 0f).normalized;
Quaternion newRotation = Quaternion.Slerp(rb.rotation, rb.rotation * rightDirection, Time.deltaTime * 1000f);
rb.MoveRotation(newRotation);
//Move Side to Side
Vector3 sideToSide = transform.right * Input.GetAxisRaw("Horizontal");
rb.MovePosition(rb.position + sideToSide * (speed * Time.deltaTime));
}
private void RunWalkStand()
{
direction = new Vector3(0f, 0f, Input.GetAxisRaw("Vertical")).normalized;
Vector3 forwardDirection = transform.forward * direction.z;
bool isRunning = direction.magnitude > 0.1f;
//Walking
if (isRunning && !Input.GetKey(KeyCode.LeftShift))
{
rb.MovePosition(rb.position + forwardDirection * (speed * Time.deltaTime));
playerAnimator.SetFloat("Speed_f", 0.5f);
}
//Running
else if(isRunning && Input.GetKey(KeyCode.LeftShift))
{
rb.MovePosition(rb.position + forwardDirection * (speed * runSpeed * Time.deltaTime));
playerAnimator.SetFloat("Speed_f", 1f);
}
//Standing
else if(isRunning == false)
{
playerAnimator.SetFloat("Speed_f", 0f);
}
}
}
`
it might be because a slerp is not a lineair line so its velocity is less when you are close to the endpoint maybe try Quaternion.RotateTowards.
I "Mostly" solved this issue, and it's an unexpected solution. The drift was solved by freezing rotation on the player in the inspector (Still don't know what was causing the player to spin though) However this caused extra jitter. I found two issues.
If I've selected ANY game object in the hierarchy, and play the game, the game is jittery, but if I click off of it onto nothing, the game runs smoother (Not completely better, but much smoother).
I'm using a Gravity script for the planet that applies gravity to the player's Rigidbody, and I believe with multiple things acting on the RB at the same time, it causes jitter. I'm thinkin of trying to greatly simplify the project, but putting the different methods from the scripts into different Update methods helps a good bit depending on the combination (Not as simple as Physics movement in FixedUpdate and camera in LateUpdate unfortunately).

Trying to get reversed movement on collision on Unity2

so I am trying to make a shooting machine that shoots bullet and bullet gets back from the same way it went through when hitting the wall without speeding up and without changing angle (just the opposite way)
i added force and tried many ways but nothing works , please help
here is my code (the last one) even though i normalized the force but i still feel like its speeding up
public Rigidbody2D rb;
private float bulletForce = 20f;
private bool collided;
Vector2 dir;
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
dir = transform.up;
}
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
dir = Vector2.Reflect(rb.position, other.contacts[0].normal);
rb.velocity = dir.normalized * bulletForce;
transform.up = dir.normalized;
}
}
this is wanted results explanation
this is current results explanation
If you just want to exactly invert the direction than
rb.velocity = -rb.velocity;
transform.up = rb.velocity;
and of course it is speeding up since you constantly add force in
void Update()
{
rb.AddForce(dir.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
why don't you just disable any friction for this bullet and set an initial velocity once?
public class CollideReflector : MonoBehaviour
{
[SerializeField] Rigidbody2D rb;
[SerializeField] Vector2 direction;
[SerializeField] float bulletForce = 20f;
[SerializeField]float smooth;
private bool collided;
// STARTER
private void Awake()
{
instance = this;
rb = gameObject.GetComponent<Rigidbody2D>();
direction = transform.up;
}
void Update()
{
rb.AddForce(direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Edge"))
{
var x = Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
Quaternion target = -x;
transform.rotation = Quaternion.Slerp(transform.rotation, x, Time.deltaTime * smooth);
rb.AddForce(-direction.normalized * bulletForce * Time.deltaTime, ForceMode2D.Impulse);
}
}
}

Movement and Jump doesn't work simultaneously

What to change here to my character moves forward and can also jump?
public class PlayerJump : MonoBehaviour {
public float jumpForce = 10f;
private Rigidbody2D myRB;
public float speed = 2f;
void Start () {
myRB = transform.GetComponent<Rigidbody2D> ();
}
public void FixedUpdate () {
myRB.velocity = Vector2.right * speed;
}
public void Jump () {
myRB.velocity = new Vector2 (myRB.velocity.x, jumpForce);
}
}
Consider using rb.AddForce(transform.up * jumpHeight, ForceMode2D.Impulse); what's happening is that you are resetting your vertical velocity when you are moving. So you also need to take into account your current velocity on your y axis, using myRB.velocity = new Vector2(speed, myRB.velocity.y);
Vector2.right is Vector2(1, 0), so all your vertical velocity sets to 0 in fixed update. For moving, you need something similar what you have for jump (keep your vertical velocity).
myRB.velocity = new Vector2(speed, myRB.velocity.y);

Unity, Stop Moving Player when he hits obstacle or bounds [duplicate]

I just started learning Unity. I tried to make a simple box move by using this script. The premise is, whenever someone presses 'w' the box moves forward.
public class PlayerMover : MonoBehaviour {
public float speed;
private Rigidbody rb;
public void Start () {
rb = GetComponent<Rigidbody>();
}
public void Update () {
bool w = Input.GetButton("w");
if (w) {
Vector3 move = new Vector3(0, 0, 1) * speed;
rb.MovePosition(move);
Debug.Log("Moved using w key");
}
}
}
Whenever I use this, the box doesn't move forward on a 'w' keypress. What is wrong with my code? I thought it might be the way I have my Vector 3 move set up so I tried replacing the z-axis with speed, but that didn't work. Could someone tell me where I am messing up?
You move Rigidbody with Rigidbody.MovePosition and rotate it with Rigidbody.MoveRotation if you want it to properly collide with Objects around it. Rigidbody should not be moved by their position, rotation or the Translate variables/function.
The "w" is not predefined like SherinBinu mentioned but that's not the only problem. If you define it and use KeyCode.W it still won't work. The object will move once and stop.
Change
Vector3 move = new Vector3(0, 0, 1) * speed;
rb.MovePosition(move);
to
tempVect = tempVect.normalized * speed * Time.deltaTime;
rb.MovePosition(transform.position + tempVect);
This should do it:
public float speed;
private Rigidbody rb;
public void Start()
{
rb = GetComponent<Rigidbody>();
}
public void Update()
{
bool w = Input.GetKey(KeyCode.W);
if (w)
{
Vector3 tempVect = new Vector3(0, 0, 1);
tempVect = tempVect.normalized * speed * Time.deltaTime;
rb.MovePosition(transform.position + tempVect);
}
}
Finally, I think you want to move your object with wasd key. If that's the case then use Input.GetAxisRaw or Input.GetAxis.
public void Update()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 tempVect = new Vector3(h, 0, v);
tempVect = tempVect.normalized * speed * Time.deltaTime;
rb.MovePosition(transform.position + tempVect);
}
"w" is not predefined unless you explicitly define it. Use KeyCode.W
Try this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMover : MonoBehaviour {
public float speed;
private Rigidbody rb;
void Start () {
rb = GetComponent<Rigidbody>();
}
void Update () {
bool w = Input.GetKey(KeyCode.W);
if (w) {
Vector3 move = new Vector3(0, 0, 1) * speed *Time.deltaTime;
rb.MovePosition(move);
Debug.Log("Moved using w key");
}
}
}
Use Input.GetKey(KeyCode.W) for getting input.
EDIT NOTE:
To move the object relative to its initial position use rb.MovePosition(transform.position+move) rather than rb.MovePosition(move)
Instead of making w a bool, you can use axis, also, in unity editor you should make it so the rigidbody movement is frozen
here is some code
void update()
{
rb.AddForce(Input.GetAxis("Horizontal"));
}
bool w = Input.GetKeyDown(KeyCode.W);

Use Accelerometer for Roll-a-ball Movement

I'm working on maze game for Android in Unity 5.1.1f1 and I have troubles with controlling my ball with accelerometer. At start I tried:
public class PlayerController : MonoBehaviour {
public GameObject sphere;
public Camera camera;
public float speed=200;
private Rigidbody myRigidBody;
void Start()
{
myRigidBody = gameObject.GetComponent<Rigidbody> ();
}
void FixedUpdate()
{
float moveH = Input.acceleration.x;
float moveV = -Input.acceleration.z;
Vector3 move = new Vector3 (moveH, 0.0f, moveV);
myRigidBody.AddForce (move * speed*Time.deltaTime);
}
}
But the ball is not moving as it should. Then I tried another solution. But my ball still doesn't move right. It seems like it's sometimes hard to move left/right/forward/backward, also it's possible my ball will rotate in the opposite direction.
public class PlayerController : MonoBehaviour {
public float speedAc = 10;
//accelerometer
private Vector3 zeroAc;
private Vector3 curAc;
private float sensH = 10;
private float sensV = 10;
private float smooth = 0.5f;
private float GetAxisH = 0;
private float GetAxisV = 0;
// Use this for initialization
void Start () {
ResetAxes();
}
//accelerometer
void ResetAxes(){
zeroAc = Input.acceleration;
curAc = Vector3.zero;
}
void FixedUpdate () {
curAc = Vector3.Lerp(curAc, Input.acceleration-zeroAc, Time.deltaTime/smooth);
GetAxisH = Mathf.Clamp(curAc.x * sensH, -1, 1);
GetAxisV = Mathf.Clamp(-curAc.z * sensV, -1, 1);
Vector3 movement = new Vector3 (GetAxisH, 0.0f, GetAxisV);
GetComponent<Rigidbody>().AddForce(movement * speedAc);
}
}
Can someone help me, please?
I have answered this one in another SO question: Unity 3D realistic accelerometer control - you've got two variants of control there, just copy the one you find fit.
If you're having more problems, ask.