In my FPS Game, I am trying to make my player throw a grenade. I know there are similar questions like this, but the posts are old and they the answers did not help me at all. When I tried to make my grenade throw using the AddForce() method, the grenade merely spawned right in front of the player, like the AddForce() method was never called. The same happened when I set its velocity to a value. It seems like the grenade won't move at all! I have made sure that:
The grenade is NOT Kinematic
It doesn't work with both gravity on and off
No Positions/Rotations are frozen
There is a rigid body attatched
There isn't a character controller attached to the grenade
The mass is only one
My code is below:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Script : MonoBehaviour {
[SerializeField] GameObject grenade;
public int throwForce = 30;
Vector3 spawnPosition;
// Use this for initialization
void Start () {
instantiateVariables ();
}
void instantiateVariables(){
}
void throwGrenade(){
print (spawnPosition);
GameObject tempGrenade = (GameObject) Instantiate (grenade, spawnPosition, transform.rotation);
Vector3 direction = new Vector3(transform.forward.x, transform.forward.y, transform.forward.z );
Rigidbody rb = grenade.GetComponent<Rigidbody> ();
if (rb != null){
rb.velocity = direction.normalized * 10f;
Destroy (tempGrenade, 10);
}
else {
Debug.LogError ("There is no rigid body on your cube!");
}
}
// Update is called once per frame
void Update () {
spawnPosition = transform.forward + transform.position;
print (spawnPosition);
if (Input.GetMouseButtonDown (1)) {
throwGrenade ();
}
}
}
Inspector:
Shouldn't you store the tempGrenade's rigidBody Component in rb instead of grenade's rigidBody? I would recommend using tempGrenade's rigidBody and then modifying rb.velocity.
Like:
rb = tempGrenade.GetComponent<Rigidbody> ();
EDIT: Corrected the line of code by removing the velocity field
Related
I am a beginner at unity and try to make a game by watching some tutorial. After finishing my game I wanted to add some more functionality which is dropping objects continuously from up to the plane. But after it dropped on the plane it rising up to a certain level and again dropped on the plane. I don't understand what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class droper : MonoBehaviour
{
// Start is called before the first frame update
MeshRenderer renderer;
Rigidbody rigidbody;
Vector3 pos1;
Vector3 pos2;
Vector3 pos3;
[SerializeField]float timeToWait =2f;
[SerializeField]float speed =0.005f;
void Start()
{
renderer = GetComponent<MeshRenderer>();
rigidbody = GetComponent<Rigidbody>();
renderer.enabled= false;
rigidbody.useGravity= false;
pos1 = transform.position;
}
// Update is called once per frame
void Update()
{
if (Time.time > timeToWait)
{
renderer.enabled= true;
rigidbody.useGravity= true;
pos2 = transform.position;
Debug.Log(pos1);
pos3=new Vector3(transform.position.x,pos1.y,transform.position.z);
if (pos2.y < pos1.y)
{
transform.position=Vector3.MoveTowards(pos2,pos3,speed);
}
}
}
}
enter image description here
You can do this in 2 ways
You can use rigidbody.velocity along the axis you want to move, you may want to disable gravity depending on what you are trying to achieve
Transform.translate is also an option but it has buggy physics so you shouldn't really use it
I'm new to Unity and to C#. I was trying to code a 2D platformer movement script, but for some reasons the code I'm creating doesn't work.
The script is referred to a circle. I've added "Rigidbody2D" and "Circle Collider 2D".
I've tried to use this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
public Rigidbody2D rb;
public void FixedUpdate()
{
if (Input.GetKey(KeyCode.RightArrow))
{
rb.AddForce(10, 0, 0);
}
}
}
The code should give an hit to the circle to make it move right, but Visual Studio says that "rb.AddForce" is an error. Can you help me, please?
Are you sure you have actually referenced the rigidbody? Did you drag the rigidbody in the editor? If you have not, you could also say the following (if the script is attached to object that holds the rigidbody you would like to move):
private Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
1)Make sure your Rigidbody component is NOT set to Kinematic.
2)Depending on the mass and linear drag of the rigidbody, you would need to change the force you apply to it accordingly. The code may be working but you would not see the body moving if you do not apply enough force.
3)Addforce() expects a Vector as an argument. This is your problem.
public float thrust; //set in editor, this is how strong you will be pushing the object
private Rigidbody2D rb;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
if (Input.GetKey(KeyCode.RightArrow))
{
rb.AddForce(transform.right * thrust); //this will move your RB to the right while you hold the right arrow
}
}
4) Set a linear drag of your rigidbody so that it can actually stop after applying the force to it. In order to make it work, set the mass and linear drag both to 1 for example and then just experiment with the thrust variable, it will eventually start moving. After that you can reduce/increase the linear drag and the thrust until you achieve the desired effect.
BONUS
If you wish to use a Vector3D the way you have tried in your code, you could do the following and it will work too:
private void FixedUpdate()
{
if (Input.GetKey(KeyCode.RightArrow))
{
rb.AddForce(new Vector3(10, 0, 0)); //this will move your RB to the right while you hold the right arrow
}
}
Because of Rigidbody2D implementation it takes Vector2 in constructor as an argument instead of simple Rigidbody which can take Vector3 and Vector2 as Vector3. Consider Vector3 v3 = new Vector2(10, 0); and
Vector2 v2 = new Vector3(10, 0, 0);
Try this
rb.AddForce(new Vector2(10, 0));
or
rb.AddForce(new Vector3(10, 0, 0));
You need to add ForceMode2D.Impulse for it to work:
using UnityEngine;
public class TestControl : MonoBehaviour
{
public Rigidbody2D rb2d;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.RightArrow))
{
rb2d.AddForce(new Vector2(5, 0 ), ForceMode2D.Impulse);
Debug.Log("RightArrow was Pressed");
}
}
}
You can find more info in here: https://www.studytonight.com/game-development-in-2D/right-way-to-move
I'm writing a script in C# in Unity that essentially functions as a switch to turn gravity on or off for a 2D Rigidbody. When the game starts, gravity should be 0 for the Rigidbody. Then when the user taps the space bar, gravity is supposed to increase to 3 (which is does). Then, however, when the player collides with a gameObject labeled 'InvisGoal', the player should teleport to another location and then gravity should be 0 again. However, the player always falls after coming in contact with InvisGoal and teleporting and I can't figure out why. This is my first project in C# so sorry for any obvious errors.. The script is here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallLaunch : MonoBehaviour {
private Rigidbody2D myRigidBody;
public GameObject Ball;
// Use this for initialization
void Start ()
{
myRigidBody = GetComponent<Rigidbody2D> ();
GetComponent<Rigidbody2D>().gravityScale = 0f;
}
// Update is called once per frame
void Update ()
{
if (Input.GetButtonDown ("Jump"))
{
GetComponent<Rigidbody2D> ().gravityScale = 3f;
}
}
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "InvisGoal")
{
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
transform.position = new Vector3 (0.61f, 1.18f, 0f);
return;
}
}
}
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
This is likely what is causing the problem.
It sounds like the RigidBody2D you are referencing to in this line is not the same as the one you retrieved beforehand with GetComponent().
GetComponent returns the component of the GameObject you call it from. Therefore in the code I mentioned above,
Ball.gameObject.GetComponent<RigidBody2D>()
and
GetComponent<RigidBody2D>()
would give you an two different RigidBody2D component if the field Ball does not refer to the same GameObject your BallLaunch script is attached to.
[
Supposing BallLaunch script is attached to the Ball you want to set the gravity of (As picture above)
Simply change:
Ball.gameObject.GetComponent<Rigidbody2D>().gravityScale = 0f;
To
GetComponent<Rigidbody2D>().gravityScale = 0f;
Also, since you already referenced your RigidBody2D in your Start method to the field myRigidBody, you can replace all subsequent GetComponent with myRigidBody.
GetComponent<Rigidbody2D>().gravityScale = 0f;
To
myRigidBody.gravityScale = 0f;
I am trying to do my player movement script in C# and for some reason, when I launch the game in unity it still doesn't work. I was wondering if after setting up the vectors in the script, if I need to say what button can be pressed to make the player move.
Here's my code that I have. (can't Post Pictures Currently)
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public float speed;
public Rigidbody rb;
void start()
{
rb = GetComponent <Rigidbody> ();
}
void fixedupdate()
{
float movementHorizontal = Input.GetAxis ("Horizontal");
float movementVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (movementHorizontal, 0.0f, movementVertical);
rb.AddForce (movement * speed);
}
}
C# is case sensitive so if this is your exact code your functions will never be called. They need to be called Start() and FixedUpdate()
You have named your methods incorrectly; The case matters. Because of this, they never get called. Instead they should be:
void Start()
and
void FixedUpdate()
Unity doesn't throw any errors because it thinks what you've written are your own private methods.
I started making a simple game in Unity3d: a tank to shoot at a wall (see image).
A GameObject is attached to the turret of the tank, and to this GameObject is attached the following script :
using UnityEngine;
using System.Collections;
public class Shooter : MonoBehaviour {
public Rigidbody bullet;
public float power = 1500f;
void Update () {
if (Input.GetButtonDown ("Fire1")) {
Rigidbody bulletRB = Instantiate (bullet, transform.position, transform.rotation) as Rigidbody;
Vector3 fwd = transform.TransformDirection(Vector3.forward);
bulletRB.AddForce(fwd*power);
}
}
}
When I press on the Fire1 button the bullet does not shoot. I put (for test) a Debug.Log("BULLET SHOOT") after bulletRB.addForce(). The message is displayed, so the script reached this point. What is wrong with my code?
Based on this somewhat similar question on Unity Answers, you should probably be instantiating the GameObject of the bullet prefab/instance, rather than its Rigidbody directly. Then, access the Rigidbody component of that new bullet and add the force.
Your adjusted Update() method would then look like:
void Update () {
if (Input.GetButtonDown ("Fire1")) {
GameObject newBullet = Instantiate (bullet.gameObject, transform.position, transform.rotation) as GameObject;
RigidBody bulletRB = newBullet.GetComponent<Rigidbody>();
Vector3 fwd = transform.TransformDirection(Vector3.forward);
bulletRB.AddForce(fwd*power);
}
}
Another thing you may want to change is using transform.forward (aka. Forward vector of the turret) rather than Vector3.forward (global forward vector Vector3(0, 0, 1), which may not match the direction of the turret).
Hope this helps! Let me know if you have any questions.
Force can be applied only to an active rigidbody. If a GameObject is inactive, AddForce has no effect.
Wakes up the Rigidbody by default. If the force size is zero then the Rigidbody will not be woken up.
The above description is taken from Unity
Therefore, I would suggest to check if the GameObject is active first.
You can test it by doing the following:
if (newBullet.activeInHierarchy === true)
{
//active
}else{
//inactive
}