My object begins to spin when collides with the wall - c#

I have in Unity a box that is followed by a camera on a plane. I'm trying to handle the collisions between the box and different objects. When it collides with different things it spins, jumps and happen weird things. I uploaded to YouTube a video to show the problem. The video.
I created an empty that has the camera and the box. This empty has rigidbody of mass 1.
The empty has a script component:
using UnityEngine;
using System.Collections;
public class Character : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter(Collision collision)
{
Debug.Log ("Entered OnCollisionEnter function");
if (collision.gameObject.name == "Wall") {
GetComponent<Rigidbody>().velocity = Vector3.zero;
Debug.Log ("Inside if statement");
}
}
}
As you can see I tried to handle the collision writing a code that stops the cube of moving.
Additional information that could help you guys:
The box
It has a box collider. Script:
using UnityEngine;
using System.Collections;
public class MoveCharacter : MonoBehaviour {
public float deltaMovement = 10f;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
Moving();
}
void Moving()
{
//Moves the character to where it needs.
if (Input.GetKey (KeyCode.A)) {
transform.Translate (new Vector3 (-deltaMovement, 0f, 0f) * Time.deltaTime);
} else if (Input.GetKey (KeyCode.D)){
transform.Translate (new Vector3 (deltaMovement, 0f, 0f) * Time.deltaTime);
}
float yRotation = Camera.main.transform.eulerAngles.y;
float movementX = Mathf.Sin ((yRotation * Mathf.PI) / 180) * deltaMovement;
float movementZ = Mathf.Cos ((yRotation * Mathf.PI) / 180) * deltaMovement;
if (Input.GetKey (KeyCode.W)) {
transform.Translate (new Vector3 (movementX, 0f, movementZ) * Time.deltaTime, Space.World);
} else if (Input.GetKey (KeyCode.S)){
transform.Translate (new Vector3 (-movementX, 0f, -movementZ) * Time.deltaTime, Space.World);
}
}
}
The wall
It is a plane with mesh collider and with or without rigidbody didn't make a difference, same problem...
Any help please?

If you are using physics you shouldn't move an object my changing it's translation, you should move it by applying forces to the object, or at least adding a velocity to it. This will allow the physics engine to correctly calculate the reactions with other rigid bodies.
If you move an object my adjusting it's translation then when a collision occurs it will be as though the object has materialised into the other object to the engine as it will be moving with no velocity etc, and you will get weird behaviour.

Related

Unity 5: How to slow down rigidbody naturally instead of sudden stop

I'm using this:
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
}
to move my character forward in the air (using jetpack). When I let go of the joystick my character stops immediately. What I want is that the character keeps moving forward after joystick is released and with time slow down and gradually stop. It looks stupid that my character stops like it hit a wall. What kind of force/velocity/transform I should use so that physics slow down my character after I let go of the joystick?
My rigidbody settings:
Mass: 100
Drag: 0
Angular drag: 0.05
Uses gravity
Not kinematic
Interpolate: interpolate
Collision detection: Discrete
Freeze position: none
Freeze rotation: all
Character also has a capsule collider that is NOT trigger and has no physics material.
EDIT: here is the full code so you can see if there is any conflicts in my code
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class JetpackController : MonoBehaviour{
Rigidbody rb;
// controller axes
[SerializeField]
public string speedAxis = "Vertical";
public string rotateAxis = "HorizontalRotate";
[SerializeField]
public float forwardSpeed;
public float upSpeed;
public float rotateSpeed;
public float rotationIgnoreZone;
public float MAX_HEIGHT;
float speedInput;
float rotateInput;
public bool leftJoystick;
public bool rightJoystick;
ParticleSystem jetpackFire1;
Vector3 originalGravity;
// access Joystick script in Standard assets to detect when right joystick is held down
Joystick joystick_left;
Joystick joystick_right;
void Start () {
if (GetComponent<Rigidbody> ()) {
rb = GetComponent<Rigidbody> ();
} else {
Debug.LogError ("Player needs to have a rigidbody.");
}
// get Joysticks
if (GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ()) {
joystick_left = GameObject.Find ("MobileJoystick_left").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
if (GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ()) {
joystick_right = GameObject.Find ("MobileJoystick_right").GetComponent<Joystick> ();
} else {
Debug.LogError ("Either gameobject with name 'MobileJoystick_right' does not exist in the scene or it does not have script called Joystick.cs attached to it.");
}
jetpackFire1 = GameObject.Find("JetpackFire1").GetComponent<ParticleSystem> ();
jetpackFire1.playbackSpeed = 5.0f;
originalGravity = Physics.gravity;
}
void FixedUpdate () {
GetInput ();
// move forward and backward according to left joysticks input
if(leftJoystick){
// left joystick held down
rb.AddRelativeForce(0, 0, forwardSpeed*speedInput, ForceMode.Impulse);
}
// if right joystick is used
if (rightJoystick) {
jetpackFire1.Play ();
if (transform.position.y < MAX_HEIGHT) {
// allow going up
//rb.AddRelativeForce (0, upSpeed, 0, ForceMode.Impulse);
rb.AddForce(transform.forward * forwardSpeed);
} else if (transform.position.y >= MAX_HEIGHT) {
// prevent player to go any further up and also falling
Physics.gravity = Vector3.zero; // no gravity to prevent player from falling
rb.velocity = Vector3.zero;
}
// rotate
// always keep rotating (player can go past look at joystick dir)
if (rotateInput >= rotationIgnoreZone || rotateInput <= -rotationIgnoreZone) {
transform.Rotate(Vector3.up * rotateInput, Time.deltaTime * rotateSpeed);
}
} else {
jetpackFire1.Stop ();
// if right joystick is released
Physics.gravity = originalGravity; // normal gravity -> player can fall
}
}
public void GetInput(){
speedInput = CrossPlatformInputManager.GetAxis (speedAxis);
rotateInput = CrossPlatformInputManager.GetAxis (rotateAxis);
// access Joystick.cs script to grab wether right joystick is pressed or not
leftJoystick = joystick_left.leftJoystickPressed;
rightJoystick = joystick_right.rightJoystickPressed;
}
}
Can't comment yet
Like J.Small said, you could multiply the velocity with a number around 0.95 to slowly slow the rigidbody down. If you put the multiplication in the Update method I suggest you to multiply the ~0.95 number with Time.deltaTime, so the velocity decrease will be proportional to the passed time.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.95 * Time.deltaTime;
//Or: rb.velocity.x
}
}
You could also apply a small amount of force instead of multiplying the velocity if you want to slow down the rigidbody in a more configurable way (the amount should be based on Time.deltaTime if you put it into Update - which gets called once a frame), but the method above is easier.
I'm not a pro at coding, so I'm not sure if this'll work for everyone, but I tried something like this to fix a similar issue.
void FixedUpdate()
{
playerRigidbody.AddRelativeForce(Vector2.up * forwardInput * playerSpeed * Time.fixedDeltaTime);
if (forwardInput <= 0)
{
playerRigidbody.velocity = playerRigidbody.velocity / 1.005f; // <-- This will gradually slow down the player when they're idle.
}
}
You could do a simple linear slow down.
void Update(){
if(leftJoystick){
rb.AddRelativeForce(0, 0, 400f, ForceMode.Impulse);
}
if(noJoystick){
rb.velocity = rb.velocity * 0.9;
}
}
Note that the update function gets called on frame update, so I would suggest putting this in a FixedUpdate() function that way the slow rate won't depend on the frame rate.

Using preferred keys to move a player in unity

I am trying to complete roll a ball tutorial (https://unity3d.com/learn/tutorials/projects/roll-ball-tutorial) in a different way by adding two balls.
So two players can play the game.
But the problem i am facing is that i want to configure the preferred keys for the second player like the firsl player uses the traditional arrow keys and the second player use w,a,s,d to move up left down right... my c-sharp code for the first player is this...
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody> ();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical); //Values for movement vector 3 takes three arguments like x y z for positions.
rb.AddForce (movement * speed);
}
}
Let me know if anyone have solution
Answered Similar question here.
The easiest solution that will require you not modify your key controls is to not use Input.GetAxis at-all. Detect each key press with Input.GetKey() and their keycodes enum. Problem solved! Now assign the two balls from the Editor. You can easily modify it to work with one ball if that's what you want.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public float speed = 80.0f; // Code for how fast the ball can move. Also it will be public so we can change it inside of Unity itself.
public Rigidbody player1RB; //Player 1 Rigidbody
public Rigidbody player2RB; //Player 2 Rigidbody
//Player 1 Code with aswd keys
void Player1Movement()
{
if (Input.GetKey(KeyCode.A))
{
player1RB.AddForce(Vector3.left * speed);
}
if (Input.GetKey(KeyCode.D))
{
player1RB.AddForce(Vector3.right * speed);
}
if (Input.GetKey(KeyCode.W))
{
player1RB.AddForce(Vector3.forward * speed);
}
if (Input.GetKey(KeyCode.S))
{
player1RB.AddForce(Vector3.back * speed);
}
}
//Player 2 Code with arrow keys
void Player2Movement()
{
if (Input.GetKey(KeyCode.LeftArrow))
{
player2RB.AddForce(Vector3.left * speed);
}
if (Input.GetKey(KeyCode.RightArrow))
{
player2RB.AddForce(Vector3.right * speed);
}
if (Input.GetKey(KeyCode.UpArrow))
{
player2RB.AddForce(Vector3.forward * speed);
}
if (Input.GetKey(KeyCode.DownArrow))
{
player2RB.AddForce(Vector3.back * speed);
}
}
// Update is called once per frame
void FixedUpdate()
{
Player1Movement();
Player2Movement();
}
}
You can define more inputs in edit -> project settings -> Input. To add more inputs just increase the size value and config the new values in. At least input name and keys to the new inputs. Lastly, in your code call the new inputs for player 2 with the names you specified in the project settings.
void FixedUpdate()
{
//float moveHorizontal = Input.GetAxis("Horizontal");
//float moveVertical = Input.GetAxis("Vertical");
// example for player 2
float moveHorizontalPlayer2 = Input.GetAxis("HorizontalPlayer2");
float moveVerticalPlayer2 = Input.GetAxis("VerticalPlayer2");
Vector3 movement = new Vector3 (moveHorizontalPlayer2 , 0.0f, moveVerticalPlayer2 );
rb.AddForce (movement * speed);
}

Shooting a ball (With gravity)

I am currently having trouble shooting a ball and adding velocity to it. The idea is that the longer you hold down "SPACE" the longer the ball will travel.
What I have so far is this for the player control:
public class PlayerControl : MonoBehaviour {
public float speed = 0f;
Vector3 enVector = new Vector3(10,0,0);
public bool laserDirection = false;
public Transform firePoint;
public GameObject RedBall;
public PlayerControl player;
// Use this for initialization
void Start () { }
// Update is called once per frame
void Update ()
{
// Press CTRL to move the platform under the ball and shoot a laser (NOT FINISHED)
if (Input.GetKey (KeyCode.LeftControl) && laserDirection == false)
{
transform.Translate(enVector * -speed * Time.deltaTime);
}
else if(Input.GetKey (KeyCode.LeftControl) && laserDirection == true)
{
transform.Translate(enVector * speed * Time.deltaTime);
}
// Sets the direction the platform will travel if pressed
if(Input.GetKey (KeyCode.LeftArrow))
{
laserDirection = false;
}
// Sets the direction the platform will travel if pressed
if(Input.GetKey (KeyCode.RightArrow))
{
laserDirection = true;
}
// Shoots a ball the longer you hold down
if(Input.GetKey (KeyCode.Space))
{
GetComponent<Rigidbody2D> ().velocity = new Vector2 (speed, GetComponent<Rigidbody2D> ().velocity.y);
Instantiate(RedBall, firePoint.position, firePoint.rotation);
}
}
// Destroy the ball
void OnTriggerEnter2D(Collider2D other)
{
Destroy (gameObject);
}
}
If you look where the get space button is you see the code I've made for the shooting. This only makes the ball travel to the right at a set speed I've chosen.
This is for changing the direction of the ball (It moves around the big black ball):
// THE DIRECTION OF THE BALL SCRIPT
public class RedBall : MonoBehaviour
{
public Transform target;
void Update()
{
// Moves the ball launcher to the left
if (Input.GetKey (KeyCode.LeftArrow))
{
transform.RotateAround (target.position, transform.forward, Time.deltaTime * 90f);
}
// Moves the ball launcher to the right
if (Input.GetKey (KeyCode.RightArrow))
{
transform.RotateAround (target.position, -transform.forward, Time.deltaTime * 90f);
}
}
}
I am struggling with how to figure out how to make the ball shoot in the direction it is facing, which depends on how it has been translated in the ball script. Additionally, how to make the ball react to the gravity when shot and how to shoot further the longer I hold hold the "SPACE" button.
If anyone knows how to do at least one of these things it would help a lot! Thank you.
(Instead of using Rigidbody2D.velocity try to use Rigidbody2D.AddForce. For turning gravity on and off use Rigidbody2D-gravityScale.
I'm not quite sure what you mean with "the longer I hold the "SPACE button". Do you want to make it a "Spring" and release it when the Space button was released?
edit:
maybe do it like this. make initial force a variable and "Load it" while the button is pressed, when it is release, instantiate the Ball and add the force to it.
i justed typed this out of the head, without testing so maybe it wont run out of the box, but the direction should be clear
if (Input.GetKey(KeyCode.Space))
{
initialForce += 0.1f;
GetComponent<Rigidbody2D>().velocity = new Vector2(speed, GetComponent<Rigidbody2D>().velocity.y);
Instantiate(RedBall, firePoint.position, firePoint.rotation);
}
else
{
if (initialForce > 0)
{
var ball = (GameObject)Instantiate(RedBall, firePoint.position, firePoint.rotation);
ball.GetComponent<Rigidbody2D>.AddForce(firePoint.rotation * Vector2.one * initialForce);
}
initialForce = 0f;
}
So I am struggling with how to figure out how to make the ball shoot
in the direction it is facing depending on how it have been translated
in the ball script.
Multiply speed by the direction you want to shoot in:
// Shoots a ball the longer you hold down
if(Input.GetKey (KeyCode.Space)) {
GetComponent<Rigidbody2D> ().AddForce(transform.forward * speed);
Instantiate(RedBall, firePoint.position, firePoint.rotation);
}
Also look into object pooling, you really shouldnt be instantiating projectiles it takes alot of memory to instantiate and destroy all the time during execution.
Also how to make the ball have the gravity when shot
protected float gravity = 1f;
protected bool isShot = false;
// Update is called once per frame
void Update ()
{
if(isShot)
rigidBody.velocity.z += gravity * Time.deltaTime;
}
shoot longer the longer I hold hold the "SPACE" button.
public float rate = 1.0f;
protected float power = 0f;
// Update is called once per frame
void Update ()
{
if (Input.GetKeyUp (KeyCode.Space))
{
UsePower(power);
power = 0f;
}
if (Input.GetKey (KeyCode.Space))
{
power += rate * Time.deltaTime;
}
}
void UsePower (float _power)
{
// Use power here
}

unity animation error resulting in animations not changing by the parameters

I am working in Unity and trying to create an animation controller that changes the direction the player is facing by playing a different animation while a button is pressed.
I keep getting this error "Assets/Maps/Map1/Entities/Player/PlayerMovement.cs(6,18): warning CS0649: Field PlayerMovement.animator' is never assigned to, and will always have its default valuenull'"
This error does not stop the game from playing, but the animation stays in its default position.
This is the code I have as a player controller which is where I alter the parameters for the animation controller. It tells me the error is on line 6 space 18.
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
Animator animator;
public float movementSpeed = 100.0f;
public bool Movement = true;
public int Direction = 0;
// Use this for initialization
void Start () {
animator.GetComponent<Animator> ();
}
// Update is called once per frame
void Update () {
if (Movement == true) {
if (Input.GetKey (KeyCode.W)) {
transform.Translate ((Vector2.up) * movementSpeed * Time.deltaTime);
animator.SetInteger("Direction",0);
}
if (Input.GetKey (KeyCode.A)) {
transform.Translate ((-Vector2.right) * movementSpeed * Time.deltaTime);
animator.SetInteger("Direction",270);
}
if (Input.GetKey (KeyCode.S)) {
transform.Translate ((-Vector2.up) * movementSpeed * Time.deltaTime);
animator.SetInteger("Direction",180);
}
if (Input.GetKey (KeyCode.D)) {
transform.Translate ((Vector2.right) * movementSpeed * Time.deltaTime);
animator.SetInteger("Direction",90);
}
else{
animator.SetInteger("Direction",360);
}
}
}
}
this is an Imgur link to Screen shots of the animator gui for unity. I would have put them directly on this screen, but I don't have the permissions to do that.
Imgur Link
I beleive this is the culprit:
void Start () {
animator.GetComponent<Animator> ();
}
it is not being assinged it should be like this :
void Start ()
{
//you have to use the variable u declared and assing it to the animator
animator = this.GetComponent<Animator> ();
}
hope that solves it.

Unity rotate while moving forward

I have the following code for my 2D game, it makes object randomly wonder on the screen. What I am having issues with, is when an object looks at the point it is going to, I would like it to rotate as it moves forward. What is happening now, is it rotates instantly to the point it is going towards. So, how can I get it to rotate slowly and move forward at the same time?
using UnityEngine;
using System.Collections;
public class Wonder : MonoBehaviour {
protected Vector2 wayPoint;
protected float speed;
// Use this for initialization
void Start () {
speed = gameObject.GetComponent<Move>().playerSpeed;
wonder();
}
void wonder(){
wayPoint = Random.insideUnitCircle * 10;
}
// Update is called once per frame
void Update () {
Vector2 dir = wayPoint - new Vector2(transform.position.x, transform.position.y);
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(new Vector3(0, 0,Mathf.Atan2 (dir.y, dir.x) * Mathf.Rad2Deg - 90));
transform.position = Vector2.MoveTowards(transform.position, wayPoint, Time.deltaTime * speed);
float magnitude = (new Vector2(transform.position.x, transform.position.y) - wayPoint).magnitude;
if(magnitude < 3){
wonder();
}
}
}
Here is an example Image:
So, once the ship gets to its point another will be created and it will move there. I am thinking I will have to have a list of 5+ points, then calculate the arch the ship needs to take adding new points as the ship hits a way point then removing old ones after. I am not sure how to do this though...
using UnityEngine;
using System.Collections;
public class Wander : MonoBehaviour {
protected Vector3 velocity;
protected Vector2 waypoint;
protected float speed;
// Use this for initialization
void Start () {
speed = gameObject.GetComponent<Move>().playerSpeed;
RandomizeWaypoint();
}
void RandomizeWaypoint(){
waypoint = Random.insideUnitCircle * 10;
}
// Update is called once per frame
void Update () {
transform.position = Vector3.SmoothDamp( transform.position, waypoint, ref velocity, Time.deltaTime * speed );
transform.rotation = Quaternion.AngleAxis( Mathf.Atan2( velocity.y, velocity.x ) * Mathf.Rad2Deg, Vector3.forward );
if( Vector3.Distance( transform.position, waypoint ) < 3 ){
RandomizeWaypoint();
}
}
}
Untested. Vector3.SmoothDamp can be pretty handy. Note the spelling also.

Categories