Why isn't my 2D bullet's collider colliding with anything? - c#

I'm trying to make a platformer game that uses 2D sprites in 3D space. For some reason, though the bullet the player shoots fires correctly from the GO that's a child of the player, it won't collide with anything (enemies, other objects, etc.) in either 2D or 3D. I have a 3D character controller on the parent player GO, but that doesn't affect the bullet object I'm firing, does it?
Colliders on everything appropriately.
Tried with IsTrigger both on and off in various combinations.
Objects are on the same layer and the same Z axis position.
//BULLET FIRING SCRIPT
void Update()
{
if (Input.GetButtonDown("Fire2") && !Input.GetButton("Fire3") &&
Time.time > nextFireTime)
{
Rigidbody2D cloneRb = Instantiate(bullet,
bulletSpawn.position, Quaternion.identity) as Rigidbody2D;
cloneRb.AddForce(bulletPrefab.transform.right *
projectileForce);
nextFireTime = Time.time + fireRate;
}
}
//____________________________________________________________
//BULLET OBJECT SCRIPT
private void Start()
{
direction = Input.GetAxisRaw("Horizontal");
if (direction == -1)
{
facingLeft = true;
}
else if (direction == 1)
{
facingLeft = false;
}
else if (direction == 0)
{
facingLeft = false;
}
if (facingLeft == false)
{
rb.velocity = transform.right * speed;
Debug.Log("Fired Bullet");
}
else
{
bulletPrefab.transform.Rotate(0, 180, 0);
firePoint.transform.Rotate(0, 180, 0);
Debug.Log("Rotated Bullet");
Debug.Log("Fired Bullet Left");
rb.velocity = transform.right * speed;
}
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log("Bullet Hit:");
Debug.Log(collider.name);
Enemy enemy = collider.GetComponent<Enemy>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
Destroy(gameObject);
}
Expected Result: Bullet object collides with other objects, prints Debug.Log output and gets destroyed.
Actual Result: Bullet object fires through, in front of, or behind other objects that also have colliders and there is no Debug.Log output. Bullet does not get destroyed and so instantiates clones infinitely when assigned input is entered.

Fixed issue by checking Default/Default in the Layer Collision Matrix under Edit-->Project Settings-->Physics. Not sure if it's supposed to be checked by default and somehow got unchecked but checking it solved the problem.

Related

Unity Rigidbody is sliding after jumping

I would like my character to jump diagonally but when it hits the ground it slides.
private void Update()
{
if (Input.GetMouseButtonUp(0) && isGrounded())
{
//jump
timeHeld = 0;
Debug.Log("MouseButtonUp = true");
rb.AddForce(jumpDirection, ForceMode2D.Impulse);
}
else if (isGrounded())
{
rb.velocity = Vector2.zero;
}
}
this code somehow works but it glitches when the player hits the ground. I need to put some amount of force to get him out of isGrounded() or he will just get some pixels up and be instantly pushed down again.
This is my isGrounded() function
private bool isGrounded()
{
RaycastHit2D raycastHit = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down, 0.1f, platformLayerMask);
return raycastHit.collider != null;
}
the problem is obviously my distance which is 0.1f in Boxcast(). Any ideas how to fix that?
No need to check the ground by yourself.
Add a unity event called OnCollisionEnter
Inside, check if the collider is the ground
If true, then velocity = zero

How unity raycast prevent double jump problem

I am trying to prevent the player to double jump, for that I am using Raycast to check if the player is in the layer Floor. My solution works sometimes, but sometimes it allows the player to double jump.
This is my code:
void Movement()
{
float movement = Input.GetAxis("Horizontal");
Vector3 playerVelocity = new Vector3(movement*speed, myRigidbody.velocity.y, speed);
myRigidbody.velocity = playerVelocity;
if (Input.GetKeyDown("space") && isGrounded)
{
Vector3 jumpVelocity = new Vector3(0f, jumpSpeed, 0f);
myRigidbody.velocity += jumpVelocity;
isGrounded = false;
Debug.Log("floor:"+isGrounded);
anim.SetInteger("AnimationPar", 3);
myAudioSource.Stop();
AudioSource.PlayClipAtPoint(jumpSound,transform.position, volumeSoundEffects);
}
else if (isGrounded && !myAudioSource.isPlaying && !levelFinished)
{
myAudioSource.Play();
}
if (!isGrounded)
{
IsGrounded();
}
}
void IsGrounded()
{
RaycastHit hit;
int mask = 1 << LayerMask.NameToLayer("Floor");
if (Physics.Raycast(transform.position, Vector3.down, out hit, 0.01f, mask))
{
//Debug.Log("Is touching floor");
isGrounded = true;
Debug.Log("floot:" + isGrounded);
anim.SetInteger("AnimationPar", 1);
if (!myAudioSource.isPlaying)
{
myAudioSource.Play();
}
}
}
The Movement method is called in Update. I think that maybe the IsGrounded method is called to fast and the player is still to close to the floor.
An easy way to prevent double jump is using a counter instead of raycast, it really makes everything easy. put a counter in this portion of the code:
if (Input.GetKeyDown("space") && isGrounded && counter <2)
{
Vector3 jumpVelocity = new Vector3(0f, jumpSpeed, 0f);
counter++;
Im unable to debug your code at this time, but another way you could do it is using OnCollisionEnter and OnCollisionExit
You can detect all things your players collides with, if one of them is the Floor then its likely hes grounded. But it would be possible to touch the floor on the side of the player while falling, to avoid this use the grounded method agian. You said it does work but sometimes fails. So try something like:
void OnCollisionEnter (Collision col)
{
if(col.gameobject.layer == LayerMask.NameToLayer("Floor") && IsGrounded())
{
isGrounded = true;
}
}
void OnCollisionExit (Collision col)
{
if(col.gameobject.layer == LayerMask.NameToLayer("Floor") && !IsGrounded())
{
isGrounded = false;
}
}
Thats untested code so im not 100% sure if it will work. The Exit may not work since IsGrounded may still be able to raycast to the ground. But if you handle your layers/collision in your levels right then you can remove the IsGrounded calls entirely.
This isnt the perfect solution by far but it might work.

Prevent moving in raycast direction when raycast hits something

I'm working on a third person controller and I'm trying to prevent movement when a raycast in front of the player hits something. Currently when the player collides with a block the blend tree is set to 0 so that it shows the Idle animation. In this case the player appears to be not moving, which it obviously isn't because it's colliding with something, but the input of the user is still there.
This is visible when the player presses the jump button, because the player moves in the direction the user was initially trying to move. In the player controller there is a part that prevents the user from moving after the jump button has been pressed during the length of the jump (Until the player is grounded again). What I'm trying to achieve is that when the user is moving against something and presses the jump button the player will just jump up and won't go in the direction the user was initially trying to go, even if there is no more collider or obstruction.
Something like if the raycast hits something the user won't be able to add movement in that direction, but is still able to turn the player away from the object and move in that direction as long as the raycast doesn't hit a collider.
I'm no c# wizard, so most of the code below comes from a tutorial. I can write a raycast myself, but have no clue how to write the rest of what I'm trying to achieve.
Edit: Current script
public RaycastHit _Hit;
public LayerMask _RaycastCollidableLayers; //Set this in inspector, makes you able to say which layers should be collided with and which not.
public float _CheckDistance = 5f;
void Update()
{
PushStates();
// Input
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
Vector2 inputDir = input.normalized;
bool running = Input.GetButton("Run");
if (IsNotBlocked())
{
Move(inputDir, running);
}
float animationSpeedPercent = ((running) ? currentSpeed / runSpeed : currentSpeed / walkSpeed * .5f);
anim.SetFloat("speedPercent", animationSpeedPercent, speedSmoothTime, Time.deltaTime);
anim.SetFloat("speedPercentPush", animationSpeedPercent, speedSmoothTime, Time.deltaTime);
// Check if walking or running
if (animationSpeedPercent < 0.51f)
{
if (ShortJumpRaycast())
{
if (Input.GetButtonDown("Jump") && Time.time > canJump)
{
ShortJump();
}
}
else
{
if (Input.GetButtonDown("Jump") && Time.time > canJump)
{
JumpWalk();
}
}
}
else
{
//Debug.Log("You are Running");
if (Input.GetButtonDown("Jump") && Time.time > canJump)
{
JumpRun();
}
}
JumpCheck();
}
void Move(Vector2 inputDir, bool running)
{
if (inputDir != Vector2.zero)
{
float targetRotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg + cameraT.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, GetModifiedSmoothTime(turnSmoothTime));
}
float targetSpeed = ((running) ? runSpeed : walkSpeed) * inputDir.magnitude;
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
velocityY += Time.deltaTime * gravity;
Vector3 velocity = transform.forward * currentSpeed + Vector3.up * velocityY;
controller.Move(velocity * Time.deltaTime);
currentSpeed = new Vector2(controller.velocity.x, controller.velocity.z).magnitude;
// Checks if player is not grounded and is falling
if (GroundCheck())
{
velocityY = 0;
anim.SetBool("onAir", false);
}
else
{
anim.SetBool("onAir", true);
}
}
bool IsNotBlocked()
{
Vector3 forward = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, forward, out _Hit, _CheckDistance + 0.1f, _RaycastCollidableLayers))
if (_Hit.collider == null)
{
Debug.Log("Raycast hit nothing");
return true;
}
GameObject go = _Hit.collider.gameObject;
if (go == null) //If no object hit, nothing is blocked.
return true;
else //An object was hit.
return false;
}
Directly before move you can raycast in the direction of the movement and if it hits something you can cancel movement.
Something like:
Vector3 velocity = transform.forward * currentSpeed + Vector3.up * velocityY;
if(!Physics.Raycast(transform.position, transform.forward, distance)
{
controller.Move(velocity * Time.deltaTime);
}
else
{
controller.Move(Vector3.up * velocityY * Time.deltaTime);
}
Something like if the raycast hits something the user won't be able to add movement in that direction
Here is an example of how you can perform a raycast to check whether something was hit or not.
//Example raycast code
//Variables
public RayCastHit _Hit;
public LayerMask _RaycastCollidableLayers; //Set this in inspector, makes you able to say which layers should be collided with and which not.
public float _CheckDistance = 5f;
//Method
bool IsNotBlocked(){
Vector3 forward = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, forward, out _Hit, _CheckDistance + 0.1f, _RaycastCollidableLayers))
if (_Hit.collider == null)
{
Debug.Log("Raycast hit nothing");
return true;
}
GameObject go = _Hit.collider.gameObject;
if (go == null) //If no object hit, nothing is blocked.
return true;
else //An object was hit.
return false;
}
Basically,
The length of the ray is CheckDistance.
RayCastCollidableLayers determines which layers an object can be in for it to be collidable with the ray we create.
The code sets a direction stored in "forward", a raycast is then performed from the transform.position (position of object this script is attached to) in direction Vector3.Forward.
_Hit saves whatever the raycast hits. An object can then be accessed through it and stored as a GameObject. I call this object 'go'.
Feel free to ask questions.

Unity 2D C# gameObject does not activate other gameObjects if statements when colliding with each other. Why?

The way this game works is that the game starts off with a Largest Ball. When the rocket hits the large ball it splits into two medium balls and then into two small balls. When the rocket hits the smallest ball it gets destroyed.
The problem I'm having is that when the rocket collides with the ball. The rocket gets destroyed, but the ball does "not" divide into two Large balls and so forth.
I just noticed this and I'm wondering if my problem will be fixed if I turn this code statement to == "smallest ball" instead of !=.
if (target.tag == "Rocket")
{
if (gameObject.tag != "Smallest Ball")
{
InstantializeBallsonoff();
}
else {
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}
}
}//ontriggerenter
This is the full code for my ball Script
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
private float forceX, forceY;
private Rigidbody2D ball;
[SerializeField]
private bool moveLeft, moveRight;
[SerializeField]
private GameObject originalBall;
private GameObject ball1, ball2;
private Ball ball1script, ball2script;
[SerializeField]
private AudioClip[] popsounds; //array
// Use this for initialization
void Awake () {
ball = GetComponent<Rigidbody2D>();
ballspeed();
}
// Update is called once per frame
void Update () {
ballmovement();
}
void InstantiatingBalls()
{
if (this.gameObject.tag != "Smallest Ball")
{
ball1 = Instantiate(originalBall); //create copy of originalball into ball1
ball2 = Instantiate(originalBall);
ball1.name = originalBall.name;
ball2.name = originalBall.name;
ball1script = ball1.GetComponent<Ball>(); //get the ball script
ball2script = ball2.GetComponent<Ball>();
}
}//InstantiatingBalls
void InstantializeBallsonoff() {
InstantiatingBalls();
Vector3 temp = transform.position; //start from current ball location
ball1.transform.position = temp;
ball1script.setmoveLeft(true);
ball2.transform.position = temp;
ball2script.setmoveRight(true);
ball1.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y
ball2.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}//InstantializeBallsonoff
public void setmoveLeft(bool moveLeft) { //canMoveLeft
this.moveLeft = moveLeft;
this.moveRight = !moveLeft; //moveRight is now false b/c we set moveLeft to true
}
public void setmoveRight(bool moveRight) {//canMoveRight
this.moveRight = moveRight;
this.moveLeft = !moveRight;
}
void ballmovement() {
if (moveLeft) {
Vector3 temp = transform.position; //current position of ball
temp.x -= Time.deltaTime; // represent time per frame
transform.position = temp;
}
if (moveRight) {
Vector3 temp = transform.position; //current position of ball
temp.x += Time.deltaTime; // represent time per frame
transform.position = temp;
}
}
void ballspeed() {
forceX = 2.5f;
switch (this.gameObject.tag) {
//this refers to gameobject that holds this script
case "Largest Ball":
forceY = 11.5f;
break;
case "Large Ball":
forceY = 10.5f;
break;
case "Medium Ball":
forceY = 9f;
break;
case "Small Ball":
forceY = 8f;
break;
case "Smallest Ball":
forceY = 7f;
break;
}//switch
}//ballspeed
void OnTriggerEnter2D (Collider2D target) {
if (target.tag == "Ground") {
ball.velocity = new Vector2(0, forceY);
}
if (target.tag == "Right Wall") {
setmoveLeft(true);
/*moveRight = false;
moveLeft = true;*/
}
if (target.tag == "Left Wall")
{
setmoveRight(true);
/*moveRight = true;
moveLeft = false;*/
}
if (target.tag == "Rocket")
{
if (gameObject.tag != "Smallest Ball")
{
InstantializeBallsonoff();
}
else {
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}
}
}//ontriggerenter
}//ball
This is partial of my code where the rocket gets destroyed when it collides with the large ball & the top. This is the other part that I am having trouble with.
void OnTriggerEnter2D(Collider2D target) {
if (target.tag == "Top") {
Destroy(gameObject);
}
string[] ballhit = target.name.Split();
/*array ballhit
split = deletes the space between two words and make it so it takes 2 spaces in the array*/
for (int s = 0; s < ballhit.Length; s++) {
Debug.Log("The array contains: " +ballhit [s]);
if (ballhit.Length > 1)
{ //ball names will always be more than 1 length "Largest Ball"
if (ballhit[1] == "Ball")
{
Destroy(gameObject);
}//destroy object
}//ballhit name length
}// name increments
}//triggerCollider
This is my full Rocket Script
using UnityEngine;
using System.Collections;
public class Rocket : MonoBehaviour {
private Rigidbody2D rocket;
private float speed = 5f;
// Use this for initialization
void Awake () {
rocket = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
rocket.velocity = new Vector2(0, speed); //x, y rocket movement
}
void OnTriggerEnter2D(Collider2D target) {
if (target.tag == "Top") {
Destroy(gameObject);
}
string[] ballhit = target.name.Split();
/*array ballhit
split = deletes the space between two words and make it so it takes 2 spaces in the array*/
for (int s = 0; s < ballhit.Length; s++) {
Debug.Log("The array contains: " +ballhit [s]);
if (ballhit.Length > 1)
{ //ball names will always be more than 1 length "Largest Ball"
if (ballhit[1] == "Ball")
{
Destroy(gameObject);
}//destroy object
}//ballhit name length
}// name increments
}//triggerCollider
}//rocket
Your code is much more complicated than it needs to be an therefore the actual error is difficult to find.
First off, your moveLeft and moveRight bools are mutually exclusive. You need only one of them. I would event prefer to replace both with a public int currentDirection which you set to 1 for right and -1 for left.
Your new ballMovement method could then simply be:
void MoveBall() // C# methods are upper-case by convention
{
transform.position += Vector3.right * currentDirection * Time.deltaTime;
}
The way you check with which type of ball you are colliding is not very safe. I would suggest you use an enum to differentiate the ball sizes.
public enum BallSizes { Largest, Large, Medium, Small, Smallest }; // The different possible values
public BallSize size = BallSizes.Largest; // The balls current size, the biggest size by default
This also allows you to store your y-axis force values in a matching array and access them easily without the use of a switch or else-if:
private float[] forcesY = new float[]{ 11.5f, 10.5f, 9f, 8f, 7f };
void SetBallSpeed()
{
forceX = 2.5f;
forceY = forcesY[(int)size];
}
I think the problem you had with the ball not splitting is is connected to this.
Upon collision, you detected the type of ball you collided with, by examining its tag. But you always Instantiate the new balls using the same prefab, and I never saw you change the tag. So what type of ball are you creating?
If you use the method I described above, you can simply assign a general tag "Ball" and handle the rest with the BallSizes-enum. When creating the new balls you can do the following:
[SerializedField] // The SerializedField property makes it show up in the inspector, even though it is private
private Ball ballPrefab; // Attention: Type "Ball"
public void IsHit() // Method to execute upon rocket collision
{
if(ball.size != BallSizes.Smallest)
{
Ball leftBall = Instantiate(ballPrefab). // Notice that, when you assign you prefab as Type "Ball", you directly get the Ball-Component as the return value.
leftball.direction = -1;
leftball.size = (BallSizes)(size + 1); // Add one to size, to get get the next enum value, which is the next smaller size.
Ball rightBall = .... // Do same stuff for the right ball
}
Destroy(this.gameObject);
}
I don't know how you plan to visualise the type of ball, but you might want to add a float[] ballScales, which you use to shrink the ball's actual size, something like: leftBall.transform.localScale = Vector3.one * ballScales[(int)size].
Finally, another reason your collision does not work might well be, that you handle it in two different places. If you destroy the rocket after it detects collision with the ball, nothing has happend to the ball yet. If the ball is checking for collision afterward it will most likely not find the rocket, because you already destroyed it. A clean way to solve this, would be to let the rocket notify the ball of the collision:
void OnTriggerEnter2D(Collider2D target)
{
if(target.tag == "Top")
Destroy(gameObject);
else if(target.tag == "Ball")
{
target.GetComponent<Ball>().IsHit(); // We know this component should exist when the object is tagged "Ball"
Destroy(gameobject);
}
}
You can then remove that from you ball collision and shorten it to this:
void OnTriggerEnter2D (Collider2D target)
{
if(target.tag == "Ground")
ball.velocity = new Vector2(0, forceY);
if(target.tag == "Right Wall" || target.tag == "Left Wall")
direction *= -1; // Inverts the direction, + <-> -
}
Phew, that was a lot.
I hope this is still relevant and answers more questions than it raises.
Happy coding!

Unity3D C# Object Movement

So I am a bit of a noob when it comes to scripting/programming and I am in need of some assistance. Currently I have the script below attached to an empty game object that is in the middle of a sphere. The empty object has a child cube that is on the outside of the sphere so when the empty object rotates around, the cube moves along the outside of the sphere.
My problem comes when that cube comes in contact with any other immovable object on the outside of the sphere, it moves and rotates around that object which is what I dont want. What I want is for the cube to stop moving in the direction the immovable object is but be able to move left/right/back. I have written code that when the cube comes in contact with the immovable object it stops the script that rotates the empty game object, but then I cant move the empty game object ever again...its just frozen there. Here is my script.
This is the script attached to the empty game object
public class SphereMotor : MonoBehaviour {
public Vector3 eulerAngleVelocity;
public Rigidbody rb;
private float speed = 45.0f;
public bool collided = false;
public float turnSpeed = 45.0f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
public void Collided()
{
collided = true;
}
public void NotCollided()
{
collided = false;
}
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow) && !collided) {
transform.Rotate (0.0f, turnSpeed * Time.deltaTime, 0.0f);
}
if (Input.GetKey(KeyCode.RightArrow) && !collided) {
transform.Rotate (0.0f, -turnSpeed * Time.deltaTime, 0.0f);
}
if (Input.GetKey(KeyCode.UpArrow) && !collided) {
transform.Rotate (turnSpeed * Time.deltaTime, 0.0f, 0.0f);
}
if (Input.GetKey(KeyCode.DownArrow) && !collided) {
transform.Rotate (-turnSpeed * Time.deltaTime, 0.0f, 0.0f);
}
}
This is the script for collision
herebool isColliding = false;
public SphereMotor _SphereMotor;
void Start()
{
_SphereMotor = GameObject.FindObjectOfType<SphereMotor>();
}
void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Player")
{
//isColliding = true;
StartCoroutine(ObjectColliding());
Debug.Log("wall hit");
}
}
void OnCollisionExit(Collision collision)
{
if(collision.gameObject.tag == "Player")
{
isColliding = false;
}
}
public IEnumerator ObjectColliding()
{
isColliding = true;
yield return new WaitForSeconds(2f);
isColliding = false;
}
void Update()
{
if(isColliding == true)
_SphereMotor.Collided();
if(isColliding == false)
_SphereMotor.NotCollided();
}
Here is a video showcasing my problem in action: https://www.youtube.com/watch?v=tkbbiTwkTqA
I tried using a Coroutine to try and fix the problem but it doesnt really work. When I hold one of the movement buttons down the cube still rotates around the immovable object. I dont really know how to approach this problem so any advice would be really appreciated!
One way would be to use collision.relativeVelocity or collision.contacts to detect from which direction the collision came, then to save some flags like collidedLeft, collidedRight, and so something similar to what you do now - on update do not rotate in some direction if one of the flags is true. But then, what it comes in some angle? You basically need to implement the whole physics system.
I would suggest a little different configuration to achieve this, that uses built in physics engine.
First, it is generally a bad practice to use transform.rotation on objects that affect rigidbodies, as it requires extra computation. It is better to work with rigidbody directly in FixedUpdate.
Now, both the inner sphere and the cube are rigidbodies. We do not need gravity or angular drag. Instead of parenting them, a better way is to connect them using fixed joint.
Next, in inner spere's rigidbody properties, make its position fixed on X, Y and Z axis (we want it to rotate only, not to move).
The cube needs a collider. Inner shpere doesnt.
And now you only need the SphereMotor, no need for collision handling at all, all is done by rigidbodies. The code is very similar to yours, just manipulates rigidbody speed instead of doing it manually:
using UnityEngine;
public class SphereMotor : MonoBehaviour {
public Rigidbody rb;
public float turnSpeed = 45.0f;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
rb.freezeRotation = false;
if (Input.GetKey(KeyCode.LeftArrow)) {
// Unity measures angular velocity in radians
rb.angularVelocity = new Vector3(0.0f, turnSpeed*Mathf.Deg2Rad, 0.0f);
} else if (Input.GetKey(KeyCode.RightArrow)) {
rb.angularVelocity = new Vector3 (0.0f, -turnSpeed*Mathf.Deg2Rad, 0.0f);
} else if (Input.GetKey(KeyCode.UpArrow)) {
rb.angularVelocity = new Vector3 (turnSpeed*Mathf.Deg2Rad, 0.0f, 0.0f);
} else if (Input.GetKey(KeyCode.DownArrow)) {
rb.angularVelocity = new Vector3 (-turnSpeed*Mathf.Deg2Rad, 0.0f, 0.0f);
} else {
rb.freezeRotation = true; // No key pressed - stop
}
}
}
I create a demo project, you can get it from my dropbox here:
https://www.dropbox.com/s/b1kjrax0repku48/SphereSampleProject.zip?dl=0
Hope that helps

Categories