I'm working on my first Unity game and I'm having a problem with this script.
void FixedUpdate ()
{
Debug.Log ("dead is " + dead);
dead = Physics.OverlapSphere (frontCheck.position, radius, whatIsWall);
if (dead == true)
{
Debug.Log ("Player died!");
Invoke ("Reset", 1);
}
}
void Reset()
{
SceneManager.LoadScene ("Game");
}
I'm trying to make the bool dead true when the player runs into a wall, using a transform in front of the player. I was using Physics2D.OverLapPoint and it worked fine, but I had to change player's physics to 3D. I'm trying to use OverLapSphere now, but Im getting an error message "Cannot implicitly convert type UnityEngine.Collider[] to bool. What should I do to make this work? Im very much a beginner to Unity and coding in general, so it's probably a simple fix. Maybe I just need to try something else? thanks.
Better Approach
I believe a better approach to detect collisions is using OnColissionEnter.
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html
That way you can have a simple check such as:
void OnCollisionEnter(Collision col) {
if (col.gameObject.tag == "Wall"){
dead = true;
}
}
Here is a short tutorial on that: https://unity3d.com/learn/tutorials/topics/physics/detecting-collisions-oncollisionenter
Using OverlapSphere
If for some reason you prefer OverlapSphere, then you need to know that it doesn't return a bool as you are expecting. Instead, it returns all colliders that overlap with the sphere.
https://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html
I believe what you are looking for is:
void FixedUpdate ()
{
Debug.Log ("dead is " + dead);
Collider[] hitColliders = = Physics.OverlapSphere (frontCheck.position, radius, whatIsWall);
if (hitColliders.length != 0) {
Debug.Log ("Player died!");
Invoke ("Reset", 1);
}
}
What should I do to make this work?
I personally would use different approach then overlap. One of the easiest solutions is to use colliders and object tags.
To answer why is your code not working. It is mainly because variable "dead" is not bool and 'UnityEngine.Collider[]' cant be value "true".
This is example of Unity prefab 1st person controller which have assigned following script. After that all object which have any collider and tag set ro "red" will so to speak react to scrip.In this case it will write "I have collided with trigger"+something.
using UnityEngine;
public class collisionTest : MonoBehaviour {
void OnTriggerEnter(Collider trigg)
{
if (trigg.gameObject.tag == "Red")
{
Debug.Log("I have collided with trigger" + trigg.gameObject.name);
//do your stuff
}
}
}
Related
So I learned that you can use a function called OnCollisionEnter to do different things on gameObjects collisions. I tried something simple :
using UnityEngine;
public class Bouncing : MonoBehaviour
{
void OnCollisionEnter(Collision collisionInfo)
{
Debug.Log("text");
}
}
I have a player with these children - Camera, Player Body and Ground Check. The Player Body has a capsule collider component (beacuse it's a capsule of course, the collider has the "Is Trigger" option unchecked.).
The Bouncer was meant to bounce me about 5 units high (I'll do it sometime, if you have any tutorials or anything that could help me then you can comment it too. :) ) The Bouncer has these components - Rigidbody (it isn't kinematic but uses gravity) and a Box Collider ("Is Trigger" option is unchecked.).
I tried to search help on the Internet, but nothing would work as I would like (beacuse it won't work at all).
Sorry for my bad English, thanks for your help everyone.
OnCollisionEnter is an event: Unity calls it when the object (which must have a Rigidbody) collides with any collider. This event may occur in both objects, the rigidbody and the hit object. In the player, the code could be like this:
public void OnCollisionEnter(Collision collision)
{
switch (collision.gameObject.tag) // based on Tag
{
case "Ball":
// do something when hitting ball
break;
case "Wall":
// do something when hitting wall
break;
}
// or based on component
if (collision.gameObject.GetComponent<Rigidbody>())
{
// do something when hitting Rigidbody gameobject
}
else if (collision.gameObject.GetComponent<Archer>())
{
// do something when hitting a object with (Archer for exp..) component
}
}
In the ball, the code is pretty much the same - the only difference is that the col structure contains info about the object hit:
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Player")
{
// this rigidbody hit the player
}
}
I have recently started to learn how to code and I am really enjoying it, I am little stuck and I'd like to have your help. I have added:
A plane
Character Controller (Named 'Matt' in Hierarchy)
A Cube (Which should change color to Red on keypress and also if
Character Controller collides with the collider on cube) + The script
is attached to the cube
I would like the CUBE to change it's color if R key is pressed (which works) or if the player controller collides with the cube's collider.
Screenshot of my scene below
using UnityEngine;
using System.Collections;
public class colorChange : MonoBehaviour
{
public GameObject cube;
private Renderer rend;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
// This will get the OBJECT to CHANGE COLOR on KEY PRESS
if (Input.GetKeyDown (KeyCode.R))
GetComponent<Renderer> ().material.color = Color.red;
print ("A Key Pressed For Red Color");
}
void OnCollisionEnter (Collision col)
{
if (col.collider.name == "Matt")
{
rend.material.color = Color.yellow;
}
}
}
Here is a screenshot of the properties on the the two objects:
The complication in your collision detection is that you're using a Character Controller, which doesn't exactly work within Unity's physics simulation. As a result OnCollisionEnter() will never be called during a collision between a Character Controller and a normal collider.
It sounds like what you need is the OnControllerColliderHit() method. As per the documentation:
OnControllerColliderHit is called when the controller hits a collider while performing a Move.
However, note that it's the Character Controller that receives the event, and not the object it bumped into. So if you do revise your code to use this, you'll need to put the event on the GameObject with the controller, and detect/change the cube's renderer colour from there:
void OnControllerColliderHit(ControllerColliderHit col) {
if (col.collider.name == "cube")
{
col.gameObject.GetComponent<Renderer>().material.color = Color.yellow;
}
}
Note: Because of all the physics-related headaches associated with using Unity's Character Controller, you may actually want to create your own version of it using a Rigidbody and a capsule collider. It will take a bit more scripting, but the solution Unity offers really doesn't work well with other parts of the engine.
Hope this helps! Let me know if you have any questions.
First if you are going to detect collision then your collider on cube shouldn't be trigger. If you are going to use it as a trigger then you should use OnTriggerEnter method. Anyway attach to the character controller another collider like sphere collider make sure it's not trigger and you are good. Use GetComponent() something like this:
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Player")
{
GetComponent<Renderer>().material.color = Color.yellow;
}
}
You need to use OnTriggerEnter instead of OnCollisionEnter
Cause your cube not really solid (cause you enabled trigger boolean in the box collider)
void OnTriggerEnter(Collider other)
{
if(other.name=="Cube")
{
transform.parent.GetComponent<Renderer>().material.color = Color.red;
}
}
also try to use Debug.Log in a lot of places to make sure you are executing or not.
That might do it.
UPDATE:
About the rend variable, since you have it private you need to assign it before executing the color changing, you'll get a NullReferenceException cause it's not assigned (the rend var)
Either make it public and assign in the inspector or do it in the Start():
rend = GetComponent<Renderer>();
Okay guys, I have managed to make it work. Below is my final code:
using UnityEngine;
using System.Collections;
public class colorChange : MonoBehaviour {
public Material color002;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
// This will get the OBJECT to CHANGE COLOR on KEY PRESS
if (Input.GetKeyDown (KeyCode.R)) {
GetComponent<Renderer> ().material.color = Color.red;
Debug.Log ("R Key Press For RED");
// This will get the OBJECT to CHANGE MATERIAL on KEY PRESS
} else if (Input.GetKeyDown (KeyCode.P)) {
GetComponent<Renderer> ().material = color002;
Debug.Log ("P Key Press For Pink Material (color002)");
}
}
// This will get the OBJECT to CHANGE COLOR if the FPS Controller collides with Cube GameObject
void OnTriggerEnter(Collider other)
{
print (other.name);
if(other.name=="FPSController")
{
GetComponent<Renderer>().material.color = Color.green;
Debug.Log ("FPS Collided with CUBE");
}
}
}
Thanks a lot for your help! Time to keep on coding :D
This might come off as a stupid question, but in an if statement, is it possible to check if the object is currently colliding with another object?
Here is what I had thought of initially (in the code snipit bellow) but for some odd reason that I can't figure out, the variable onFloor is sometimes false when the object is being pushed upwards by the Platform.
void OnCollisionEnter2D(Collision2D c)
{
switch(c.gameObject.tag)
{
case "Platform":
onFloor = true;
break;
default:
break;
}
}
void OnCollisionExit2D(Collision2D c)
{
switch(c.gameObject.tag)
{
case "Platform":
onFloor = false;
break;
default:
break;
}
}
And for that reason, I am asking if there are any ways to detect if the circle collider of said object is colliding with box collider of intersecting object while in code.
something like
if(CircleCollider2D.CollidingObject != null && CircleCollider2D.CollidingObject.tag == "Platform")
{ /*Code I'd like to do here*/ }
Now that's only my imagination trying to think of some way of it that could work but you get the point.
So, I ask, are there any solutions for my imagination?
After discussing with Programmer, IsTouching is underlined and giving the error: 'Collider2D' does not contain a definition for 'IsTouching' and no extension method 'IsTouching' accepting a first argument of type 'Collider2D' could be found (are you missing a using directive or an assembly reference?).
Here is the slimmed down code:
using UnityEngine;
public class Ball : MonoBehaviour
{
Vector2 jumpVelocity;
public Collision2D platform;
// Use this for initialization
void Start()
{
jumpVelocity = new Vector2(0, rigidbody2D.gravityScale * 100);
}
void FixedUpdate()
{
if (Input.GetKey(KeyCode.Space) && collider2D.IsTouching(platform))
{
rigidbody2D.AddForce(jumpVelocity, ForceMode2D.Force);
}
}
}
note that even changing collider2D to a Collision2D variable and taking that variable.collider.IsTouching results the same error.
Are there different solutions than OnCollisionEnter2D
Yes. Many of them!
CircleCollider2D, other 2D colliders and its base class Collision2D, have built in functions to do this.
public bool IsTouching(Collider2D collider); //Check collision by the provided collider
public bool IsTouchingLayers(); //Check collision by any collision
public bool IsTouchingLayers(int layerMask); //Check collision by layer
public bool OverlapPoint(Vector2 point); //Check collision by position
The first function is more appropriate for this.
Simple Example:
Collision2D collider1;
Collision2D collider2;
void Update()
{
//Checks if collider1 is touching with collider2
if (collider1.collider.IsTouching(collider2.collider))
{
}
}
Example with the OnCollisionEnter2D function:
public CircleCollider2D myCircleCollider;
void OnCollisionEnter2D(Collision2D c)
{
if (c.collider.IsTouching(myCircleCollider))
{
}
}
Maybe what you are looking for is the OnCollisionStay method, this one will fire as long as they are touching each other.
There is some more info in the link here: https://docs.unity3d.com/ScriptReference/Collider2D.OnCollisionStay2D.html
I'm newbie programming Game with Unity Engine. I have searched "How to load animation from assets in unity " But haven't find solution.
I'm handle Trigger of collider
void OnTriggerCollisionEnter2D(Collision2D coll){
if(coll.gameObject.tag = "Player"){
//try to load animation
}
}
Help me if you know ! Thanks
First of all, I think you will have hard time making my solution work because it looks like you lack Unity basic stuff.
OnTriggerCollisionEnter2D is not a valid callback function to detect Trigger.
OnTriggerEnter2D(Collider2D coll) is what you are looking for.
Secondly, don't anything during onTrigger. Load the animation in the Start() function then play it in the OnTriggerEnter2D function.
Also if(coll.gameObject.tag = "Player") should be if(coll.gameObject.tag == "Player"). Notice the double '='. You compare with double '=' not one. but not efficient. If possible, use coll.gameObject.CompareTag instead of coll.gameObject.tag ==.
Put the Animation in the Assets/Resources/Animation folder
Animation animation;
AnimationClip animanClip;
string animName = "walk";
// Use this for initialization
void Start()
{
//Load Animation
loadAnimation();
}
void loadAnimation()
{
GameObject tempObj = Resources.Load("Animations/" + animName, typeof(GameObject)) as GameObject;
if (!tempObj == null)
{
Debug.LogError("Animation NOT found");
}
else
{
animation = tempObj.GetComponent<Animation>();
animanClip = animation.clip;
animation.AddClip(animanClip, animName);
}
}
public void OnTriggerEnter2D(Collider2D coll)
{
if (coll.gameObject.CompareTag("Player"))
{
animation.Play(animName);
}
}
Finally, study these tutorials.
Unity Scripting Tutorial
Unity Physics Tutorial
Other Unity Tutorials
I have a 2.5d type game, with falling blocks (like tetris) and orthographic projection setup (I've setup my game as "3D" type).
I've defined a block like this:
public class Block{
public Block () {
this.gameObj = GameObject.CreatePrimitive (PrimitiveType.Cube);
}
public GameObject gameObj;
}
I have a BoardMgr (GameObj + script only component), where I spawn these blocks and store them in an array:
public class BoardMgr : MonoBehaviour {
protected Block[] blocks;
protected Block[,] board;
}
In BoardMgr::update(), blocks are falling down one after the other (like tetris). Now, I'd like to figure out when I click on a block, which block object is it. This is the click detection code:
if (Input.GetMouseButtonDown(0)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Debug.Log ("Ray hit block");
// How do I find which block got hit here ?
} else {
Debug.Log ("Ray missed block");
}
}
When I click on a block, I do see the ray hit block on console, but then, how do I access which "Block" object got hit ? From RayCastHit, hit object, how do I decode which Block does it reference ?
I'm new to unity (2 days old) but not new to gamedev. Trying to find my way through unity here. I'd appreciate if someone can point me in the right direction here.
//Check the GameObject by name
if (hit.collider.name == "brainydexter")
{
Debug.Log("Hit: "+hit.collider.name);
}
//Check the GameObject by tag
if (hit.collider.CompareTag("brainydexterTag"))
{
}
//Check the GameObject by GameObject instance
GameObject otherGameObject = gameObject;
if (hit.collider.gameObject == otherGameObject)
{
}
EDIT: This is what you need
Use array to loop through the blocks then compare the gameobject instance.
for (int i = 0; i < blocks.Length; i++)
{
if (hit.collider.gameObject == blocks[i].gameObj)
{
Debug.Log("Block hit is " + blocks[i].gameObj);
break;
}
}
In your if block use the hit parameter to detect which object was hit , because it has the information what the ray collided with , example hit.collider.tag == "myBlock"
I like your question. And I think I got the key of what make the above 2 answers be not you want.
Usually, unity developers want to make this kind of block, they will create a cube and add script as element to it to make a prefab.
However, What you do to define a block is more programmer, creating a C# class with a primitive cube.
I think one way is to check the block's position.x and z with the position of each block in the array .because the blocks are dropping, then just y is changing, to check x and z is a solution.
Hope help.