I am a total beginner at Unity3d. I have some background in android programming, but no C# experience whatsoever. The first thing I am trying to do is to create a clone of flappy bird game, called flappy plane, according to this tutorial
http://anwell.me/articles/unity3d-flappy-bird/
The problem is, when I tried to write a script that allows player to move (player.cs) with the code
using UnityEngine;
using System.Collections;
public class player: MonoBehaviour {
public Vector2 jumpForce = new Vector2(0,300);
public Vector2 jumpForce2 = new Vector2(0,-300);
// Use this for initialization
// Update is called once per frame
void Update () {
if (Input.GetKeyUp("space")){
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
}
}
}
I get an error "An Object reference is required to access non-static member 'UnityEngine.Rigidbody2D.velocity'". I have googled that and it is suggested to access Rigidbody2d with GetComponent().velocity,
so I changed
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
with
GetComponent<Rigidbody2D>().velocity = Vector2.zero;
GetComponent<Rigidbody2D>().AddForce(jumpForce);
The error is gone and I am able to add the script to the object, still I don`t get the desired action - after I hit play the object turns invisible and just falls down, does not react to spacebar button. What am I doing wrong?
Thanks for the answer.
It's possible that you're not adding enough force to have the object move upwards.
There's technically nothing wrong with your code. (Although you do have somethings mixed up in your question). The problem is in the fact that you're not adding ANY force upwards every single frame.
Essentially, at the moment, your player object is in free-fall the instant you hit the play button, and you're adding a minuscule force to the player only on the frames that the space bar is pressed.
To solve this, here's what you should be doing
Add an upward force to counter-act the force of gravity every frame. You can do this in two ways.
a. Set the rigidbody's velocity.y to 0 BEFORE detecting the space bar (this is really a hacky way, but it'll suffice and doesn't need any more code)
b. Add an upward force to the player which will nullify the effect of gravity. Just use F = mg to get the value of force you'd need to add.
You could, alternatively set the isKinematic property to true by default on the Player's rigidbody, set it to false on pressing the space bar, and back to true after a few frames (5 - 6 frames)
make sure your player object and the ground both have BoxCollider2D colliders to keep above ground.
you could keep a reference stored for the rigidBody like Rigidbody2D myRigidbody;
then in start put myRigidbody = GetComponent<Rigidbody2D>(); then you would use like myRigidbody.AddForce(jumpForce); your jumpForce2 though is shooting your player downward you should not need it in a jump as the physics and gravity will apply with the rigidbody.
incase your input is not set up in the project settings try to fire the jump with
Input.GetKeyDown(KeyCode.Space);
Related
First, I know that this question has been asked a lot, but I cant find a solution, so mi problem is, Im making an educational game, and I have a vein and the blood flow (with many box colliders) and a single blood cell (also with a box collider) however i want the cell to destroy when it reaches the wall collider, but it doesn't it just stays there, here is the project!
http://tinypic.com/r/10706es/9
(cant upload images because of my reputation, sorry)
The collider where I want to destroy my cell is the pink collider, however when it touches it it just does nothing, here's my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void OnCollisionEnter(Collision col)
{
print("hihi");
if (col.gameObject.tag == "Collider")
{
Destroy(gameObject);
}
}
}
Also, here is the AddForce script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AddForce : MonoBehaviour {
public float thrust;
public Rigidbody rb;
private Vector3 up;
private bool move;
void Start()
{
rb = GetComponent<Rigidbody>();
up = new Vector3(0, 1, 0);
move = false;
}
void FixedUpdate()
{
if (Input.GetKey("space"))
{
if (rb.velocity.magnitude < 5)
rb.AddForce(up * thrust);
move = true;
}
else
{
if (move == true)
rb.velocity = new Vector3(0, -0.5F, 0);
}
}
}
thanks for your help guys! :D
It can be several things, whether you are using OnTriggerEnter or OnCollisionEnter:
Missing RigidBody (the most common). At least one of the GameObjects involved needs to have a RigidBody. (check if at least one of them have a RigidBody attached and, if you are using OnCollisionEnter, does not have the "Is Kinematic" checked). See the below collision matrix for more information.
Missing tag. The GameObject from collision does not have a "Collider" tag (try to remove the if statement to test it) (to compare tags, use collider.gameObject.CompareTag("Collider"), it has a better performance)
Undetectable collision. The physics Layer Collision Matrix is set to not detect collision between the layers the objects are (enter Edit > Project > Phisics and check if the encounter of the layer of both GameObjects are checked inside Layer Collision Matrix)
Wrong Collider configuration. one or both of the GameObjects have a small/wrong placed or absent Collider (check if they both have a Collider component and if their size are correct)
If it's working, you should be able to press play and drag one GameObject into the other one and your Debug.Log will appear.
As an advice, use tag names that better describe the group of GameObjects that will be part of it, like "RedCells" or "WhiteCells". It'll be easier to configure the Layer Collision Matrix and improve the performance of your game.
Another advice: for colliders that just destroys another GameObject (don't react, like bump or actually collide) I use triggers. That way, the collision between them will not alter anything in the remaining GameObject (like direction/velocity/etc). To do that, check the Is Trigger in the Collider and use OnTriggerEnter instead of OnCollisionEnter.
Source
some times you added Nav Mesh Agent component to your game object ( to auto route operation in strategic game and ...).
in this case, this game object does not attend to collider.
So, if you really need this Nav Mesh Agent, you should add Nav Mesh Obstacle to other fixed game object and also add Nav Mesh Agent to other movable game object.
I have a few followup questions which might lead to a solution.
First, does the object holding your 'collision' script have a rigidbody and a collider on it?
Second, does the wall have both a rigidbody and collider?
Usually if those conditions are met, then collisions will work.
A couple other things that could be the problem:
Check if you have istrigger checked for either object and make sure it is unchecked.
Check and make sure the rigidbodies on both are non-kinematic.
I've finally fixed it, I dont really know if this was the problem, but i just removed the rigidbody from the parent of the wall and it started working!, I dont know what the rigidbody did, but just with that the problem was fixed, thank you all for your help! :D
Ensure the following things are considered in your code,
All gameobject should contain collider attached and the player
gameobject should contain the rigidbody component in it.
The collider size should change to the width and height of the
component instead of default (1,1) values.
I have a game I am creating in Unity. It has a table with 30 cubes on it. I want a user to be able to shuffle the cubes on the table using their mouse/touch.
I am currently using a ray to get the initial table/cube hit point then accessing the rigidbody component on the cube to apply a force using AddForceAtPosition, happening in an OnMouseDrag. I am also pulling out my hair trying to figure out how to apply force in the direction from the mouse's last position to the hit point on the rigidbody of the cube.
Can someone please help me? An example would be great. I would share my code but I am a spaghetti code monster and fear criticism... Thanks much!
If I understood correctly, is something like this you want to achieve? https://www.youtube.com/watch?v=5Zli2CJGAtU&feature=youtu.be
If so, first you have to add your cubes and table to a new layermask, this step is only necessary if you don't want your ray to hit other colliders that might mess with your result.
After this you should add a tag to all the cubes you want to aplly the force, in my case I added a new tag called "Cubes".
You can search on youtube this if you don't know how to do it, there are plenty of tutorials to help you.
After that you create a new script and attach to the camera. Here is my script:
public class CameraForceMouse : MonoBehaviour
{
public LayerMask layerMask;
RaycastHit hit;
Vector3 lastPosition;
// Start is called before the first frame update
void Start()
{
lastPosition = new Vector3();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 200f, layerMask))
{
if (hit.transform.CompareTag("Cubes"))
{
Rigidbody rb = hit.transform.GetComponent<Rigidbody>();
Vector3 force = (hit.point - lastPosition).normalized * 55f;
rb.AddForceAtPosition(force, hit.point);
}
lastPosition = hit.point;
}
}
}
}
Just want to say that there are a lot of ways to achieve the same thing, this is the way I decided to do, but there are probably other (maybe even better) ways of doing this.
Explaining the code:
The first thing is a public LayerMask that before you play the game you will have to select your camera in your scene and look for the script on the editor in the right side and select witch layerMask you added to your cubes and table.
If you don't know how raycast works, here is the documentation: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html but you can also search on youtube.
The important thing here is the new vector being created to define the direction of the force.
First we declare a global variable called LastPosition, and for every frame that we are clicking, we will check for a collision, and if this collision happens, we will then create a new vector going out of the last position the mouse was to the position the mouse is now Vector3 force = (hit.point - lastPosition), than we normalize it because we only care about the direction and multiply it by the amount of force we want, you can make it as a nice variable but I just put it there directly.
Then, after you've applied the force to the position the ray hit the object, you have to define that this is now your last position, since you are going to the next frame. Remember to put it outside of the Tag check, because this is checking if the object we collided with is the cube we want to apply the force or if it is the table. If we add this line lastPosition = hit.point; inside of this check it will only assign a new lastPosition value when we hit the cube, and would lead to bugs.
I'm not saying my answer is perfect, I can think of a few bugs that can happen, when you click outside the table for example, but is a good start, and I think you can fix the rest.
I would like to use a characters tongue so instead of shooting a bullet, it goes toward the enemy, licks it, and comes back. I got this wording from this question: Unity shooting with Tongue 2d game (hasn't been answered and is 4+ years old). The only difference is my character moves.
I have this code from looking at a shooting tutorial so when you click the tongue prefab generates and is at the correct angle. I need it to grow on click and shrink back.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LineController : MonoBehaviour
{
public GameObject player;
private Vector3 target;
public GameObject crosshairs;
public GameObject tonguePrefab;
// Start is called before the first frame update
void Start()
{
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
target = transform.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z));
crosshairs.transform.position = new Vector2(target.x, target.y);
Vector3 difference = target - player.transform.position;
float rotationZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
if (Input.GetMouseButtonDown(0))
{
shootTongue(rotationZ);
}
}
IEnumerator shootTongue(float rotationZ)
{
GameObject t = Instantiate(tonguePrefab) as GameObject;
t.transform.position = new Vector2(target.x, target.y);
t.transform.rotation = Quaternion.Euler(0.0f, 0.0f, rotationZ);
yield return new WaitForSeconds(2000);
t.SetActive(false);
}
}
I was also trying to make it disappear after whatever time and with that it doesn't work at all?
If the prefab is just a line with a simple texture I suggest using a line renderer:
Create an empty transform that starts on the mouth and then it move untill it reaches the crosshair. The movement is done using Vector2.MoveTowards.
Your tongue will no be a line renderer component. This line renderer will have 2 points, the start which is static, and the end which you have to update on the Update() for example, to correspond to the positions of the empty transform in item 1.
If you really wish to expand a tongue gameobject instead, then you are going to need a bit of math, this answer has what you need but in 3D:
https://answers.unity.com/questions/473076/scaling-in-the-forward-direction.html
1) I suggest creating sprite/sprite sheet animations with Mecanim or relatively new Skeletal Animation with Anima2D. With these systems you can create nice animations, transitions, even animate the sphere collider to trigger collisions and actions, change active state of your objects, etc. and control the animation with very little code. This way you can get best effects in my opinion.
As tongue is not a bullet... :) You only need one. I don't think you want to Instantiate/Create prefabs every time you press the lick button. Instead you should just turn your tongue object on/off (gameObject.SetActive). You can also change your object active state within the animation. So if you don't know how to code it you can do most of it in the Animation window and use very simple code to play the animation when you press the lick button. Whenever a sphere collider touches something you can tell the Animator Controller to play a 'roll back' animation and it will transition nicely to the start position.
There are many tutorials about Mecanim, Animations, 2D Animations, Anima2D, Animator Controller out there.
2) If you need very good control over the tongue you could create a custom mesh and control it via script but this is far more difficult.
3) The reason why your object is not turning off is probably because you wrote WaitForSeconds(2000) so it will turn off after 2000 seconds - more than half an hour. You should also call it with StartCoroutine(shootTongue()) as it is a Coroutine. Again if you want to turn off the object don't create new ones every time. If you want to keep creating new objects you should Destroy the objects instead. Otherwise you will end up with a lot of deactivated tongues in your scene and I don't think you needs that many tongues.
In Unity3D I have got a gameobject that is attached with a box collider and physic material. The hand controller model is also attached to a box collider and physic material. When the gameobject collides with the hand controller, the CollideWithController logs on the console. However, the gameobject does not change direction.
if (other.CompareTag("HandController"))
{
Debug.Log("CollideWithController");
var magnitude = 1000;
var force = transform.position - other.transform.position;
force.Normalize();
gameObject.GetComponent<Rigidbody>().AddForce(force * magnitude);
}
Without seeing/knowing what other is, its hard to say, but generally there could be two problems:
transform.position-other.transform.position doesn't actually result in the direction you expect. To determine this, print the value or display it using Debug.DrawRay.
The force you're adding might not be enough to change direction, or there are other forces canceling it out.
var force = transform.position - other.transform.position;
You will get a direction vector to get other to the position of this. So you are moving into the collision, reversing the vector should fix your issue.
When you modify physics value like here with AddForce, you should do it in the FixedUpdate to minimize the risk of bug. (It can work outside of the FixedUpdate, but in most case it will create unwanted behavior).
In your code you use AddFroce, but if the actual force of the gameObject is greater than this the force you add will just slow the actual movement of the gameobject and not reverse it.
I think the best way to change the movement of your gameObject is to use the velocity vector and to reflect it.
One more advice : Don't use physics for gameplay system. Physics is something very powerfull, it can bring a lot of emergent behavior, but it's a chaotic system. And when it's about gameplay you don't want chaos you want control and consistency.
Unity doc :
Velocity : https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
Reflect : https://docs.unity3d.com/ScriptReference/Vector3.Reflect.html
First, I know that this question has been asked a lot, but I cant find a solution, so mi problem is, Im making an educational game, and I have a vein and the blood flow (with many box colliders) and a single blood cell (also with a box collider) however i want the cell to destroy when it reaches the wall collider, but it doesn't it just stays there, here is the project!
http://tinypic.com/r/10706es/9
(cant upload images because of my reputation, sorry)
The collider where I want to destroy my cell is the pink collider, however when it touches it it just does nothing, here's my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void OnCollisionEnter(Collision col)
{
print("hihi");
if (col.gameObject.tag == "Collider")
{
Destroy(gameObject);
}
}
}
Also, here is the AddForce script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AddForce : MonoBehaviour {
public float thrust;
public Rigidbody rb;
private Vector3 up;
private bool move;
void Start()
{
rb = GetComponent<Rigidbody>();
up = new Vector3(0, 1, 0);
move = false;
}
void FixedUpdate()
{
if (Input.GetKey("space"))
{
if (rb.velocity.magnitude < 5)
rb.AddForce(up * thrust);
move = true;
}
else
{
if (move == true)
rb.velocity = new Vector3(0, -0.5F, 0);
}
}
}
thanks for your help guys! :D
It can be several things, whether you are using OnTriggerEnter or OnCollisionEnter:
Missing RigidBody (the most common). At least one of the GameObjects involved needs to have a RigidBody. (check if at least one of them have a RigidBody attached and, if you are using OnCollisionEnter, does not have the "Is Kinematic" checked). See the below collision matrix for more information.
Missing tag. The GameObject from collision does not have a "Collider" tag (try to remove the if statement to test it) (to compare tags, use collider.gameObject.CompareTag("Collider"), it has a better performance)
Undetectable collision. The physics Layer Collision Matrix is set to not detect collision between the layers the objects are (enter Edit > Project > Phisics and check if the encounter of the layer of both GameObjects are checked inside Layer Collision Matrix)
Wrong Collider configuration. one or both of the GameObjects have a small/wrong placed or absent Collider (check if they both have a Collider component and if their size are correct)
If it's working, you should be able to press play and drag one GameObject into the other one and your Debug.Log will appear.
As an advice, use tag names that better describe the group of GameObjects that will be part of it, like "RedCells" or "WhiteCells". It'll be easier to configure the Layer Collision Matrix and improve the performance of your game.
Another advice: for colliders that just destroys another GameObject (don't react, like bump or actually collide) I use triggers. That way, the collision between them will not alter anything in the remaining GameObject (like direction/velocity/etc). To do that, check the Is Trigger in the Collider and use OnTriggerEnter instead of OnCollisionEnter.
Source
some times you added Nav Mesh Agent component to your game object ( to auto route operation in strategic game and ...).
in this case, this game object does not attend to collider.
So, if you really need this Nav Mesh Agent, you should add Nav Mesh Obstacle to other fixed game object and also add Nav Mesh Agent to other movable game object.
I have a few followup questions which might lead to a solution.
First, does the object holding your 'collision' script have a rigidbody and a collider on it?
Second, does the wall have both a rigidbody and collider?
Usually if those conditions are met, then collisions will work.
A couple other things that could be the problem:
Check if you have istrigger checked for either object and make sure it is unchecked.
Check and make sure the rigidbodies on both are non-kinematic.
I've finally fixed it, I dont really know if this was the problem, but i just removed the rigidbody from the parent of the wall and it started working!, I dont know what the rigidbody did, but just with that the problem was fixed, thank you all for your help! :D
Ensure the following things are considered in your code,
All gameobject should contain collider attached and the player
gameobject should contain the rigidbody component in it.
The collider size should change to the width and height of the
component instead of default (1,1) values.