I'm learning Unity by trying to do things and then when ofc failing (Because that's life about XD) then I'll try to find some scripts to learn from.
I was trying to make a smooth platformer controller and then ran into a video from Brackeys
I'm having trouble understanding this line of code:
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
(Full script can be found here: https://github.com/Brackeys/2D-Character-Controller/blob/master/CharacterController2D.cs)
It's that line 54 the one that is making me have problems.
if (colliders[i].gameObject != gameObject)
What is he comparing? The first one is the gameobject attached to the collider but the second one is the default class, can someone explain what is he trying to do here?
Notice that Monobehvaiour inherits from component. So it has access to all its properties gameObject, transform ..etc. Check component documentation
So in the snippet
if (colliders[i].gameObject != gameObject)
{
m_Grounded = true;
if (!wasGrounded)
OnLandEvent.Invoke();
}
you are comparing the specific array's object (colliders[i].gameObject) with the current monobehaviour the code is running in (gameObject or this.gameObject).
In a class, you can access all the public and protected members it inherits from skypping the this keyword, as it can be understood you refer to the current instance by default.
Hope that makes sense.
Related
im trying to track collsion on a unity project and i dont get whats wrong
thats the code i'm working with.
im trying to destroy an object on collision but it doesnt work for some reason.
void OnCollisionEnter(Collision col)
{
if (col.collider.gameObject.tag == "Enemy")
{
Destroy(col.gameObject);
Debug.Log("collided");
}
}
it hits the object but nothing happends i dont get a message and the object doesnt get destroyed
Assuming that the script you posted is a component of some kind of a character (which it should be since you are looking for an Enemy using its tag) and you have proper Rigidbody components with proper settings and Colliders, you should use:
void OnCollisionEnter(Collision col)
{
// You can also use col.gameObject.tag == "Enemy" since it does the same thing as CompareTag().
// Although using col.gameObject.tag == "Enemy" is less performant.
if (col.gameObject.CompareTag("Enemy"))
{
// Using print to get proper information on what is happening.
print("destroyed " + col.gameObject.name);
// Destroying the gameObject with the tag "Enemy"
Destroy(col.gameObject);
}
}
If you wanted to destroy the player object then you should change the tag accordingly and have this script as a component of the enemy.
The most common issues if nothing is showing up can be:
the object has no RigidBody (or RigidBody2D if you are in a 2D project) component
the 2 objects are in 2 layers which don't collide with others (or the same layer which don't collide with itself). Check both objects' layers, and go to Edit -> Project Settings -> Physics (or Physics2D if the project is in 2D) and go at the bottom and check that the layers collide with each other (the check box is on)
one of the 2 colliders is in 2D and the other in 3D
Okay so basically im working on this test project that relies heavily on movement and momentum to complete levels, with a bit of parkour. I need a collider for two reasons, 1. The player touches an object at the end and gets put back into the menu. 2. If the player falls out of the map they die.
I tried a bit messing around with Colliders and at the Docs and while usually id figure it out ive been stumped for 20 minutes looking at Unity's docs and a few questions from here.
public GameObject objectCollider;
public GameObject anotherCollider;
void OnCollisionEnter(Collision collision)
{
if (CollisionDetection.IsTouching(objectCollider.gameObject, anotherCollider.gameObject))
{
Destroy(plr);
}
}
This is what I got so far. I get an error from here and if I switch it to if collider object == the other it errors out.
Basically what I want (If you perfer to just post the answer code but comments on it would still be helpful so i learn!) is for one gameobject (player (but in code its objectCollider)) to be detected if it touches the other (a cube (in code its anotherCollider)) and to execute code (for example Destroy(playerObject))
Thank you for any help you bring here, links, code anything!
Hopefully this is what you're looking for:
public void OnCollisionEnter(Collision collision)
{
if (collision.collider.name == "endObject")
{
//put back into the menu
}
}
Once your player enters a collision, it checks the name of whatever object it collided with. Then you can execute what code you want in the if statement.
You can use collision.collider for many other things, such as collision.collider.tag, but this should give you a start.
I want my Player to interact with object, so I use Fungus and a script that when the Player is close enough to the object and I press E, it sends a message to Flowchart to activate a block. But it doesn't work.
The script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EventTrigger : MonoBehaviour
{
public bool enter;
int count = 1;
// Use this for initialization
void Start()
{
enter = false;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player" || other.gameObject.tag == "NPC")
{
enter = true;
if (enter && Input.GetKeyDown(KeyCode.E))
{
Fungus.Flowchart.BroadcastFungusMessage("StartConversation");
}
}
Debug.Log("Entered");
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player" || other.gameObject.tag == "NPC")
{
enter = false;
count = 1;
}
Debug.Log("Exited");
}
}
OnTriggerEnter is called once, and you are listening to input only during one frame.
Consider moving this part to Update:
if (enter && Input.GetKeyDown(KeyCode.E))
{
Fungus.Flowchart.BroadcastFungusMessage("StartConversation");
}
or changing OnTriggerEnter to OnTriggerStay
I'm unfamiliar with Fungus, however, as mentioned in the comments, you're having trouble getting the event to be called upon Collision.
Please take the following into account:
Colliders must be marked IsTrigger for OnTriggerXXX to be called, however, trigger colliders are non-physical, this means if you only have 1 trigger collider in your gameobject, other physical objects can pass through them. To fix this, you can either add a second collider with IsTrigger unchecked, OR, you can uncheck IsTrigger and use OnCollisionXXX instead. I'd suggest the latter solution.
Make sure your colliders can actually collide.
Go to "Edit > Project Settings > Physics", scroll down until you see "Layer Collision Matrix" and make sure the checkbox in the intersection of your objects' layers is checked.
Make sure the two colliders can actually collide during play. This is common with character collisions. You might have a simple box or cylider physical collider around your characters, but have an inner mesh collider be the trigger on your NPC. This way your player character can never collide with the trigger inside the physical collider.
This may sound stupid, but make sure you added your script to correct object. I've lost the count of how many times I went through an unecessary frustration after writting a script and forgetting to add it to the test object.
This should be enough to ensure your events are actually called.
Now, please note that, as pointed out by Hermesis, you're trying to read input in a 1-frame event. You're also using Input.GetKeyDown() which is also a 1-frame check, that is, it will only return true on the frame when the key state has changed.
In your code, the condition (enter && Input.GetKeyDown(KeyCode.E)) will only ever be true, if the user happens to press the key in the exact frame the collision begins.
Again, as noted by Hermesis, consider using "OnXXXStay" instead of "OnXXXEnter".
Here are some tips:
Use OnXXXEnter to display a message to the player so he knows he is in contact with an interactable, and also knows which key(s) can do what.
Use OnXXXStay to respond to keypresses only while the collision is happening.
Use OnXXXExit to clear the message that was set upon collision.
I hope this helps.
I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.
I have an issue with the GetComponent(GUIText) the error i get is
There is no 'GUIText' attached to the "#######COUNTER(Clone)" game object, but a script is trying to access it.
Here is my code:
var UItecxt = GameObject.Find("#######COUNTER(Clone)");
var txtconvert = UItecxt.GetComponent(GUIText);
print(txtconvert);
txtconvert.text = counternumb.ToString();
I HAVE a GUIText on my clone! What is the issue? Thanks!
Your problem is that there is no GameObject named "#######COUNTER(Clone)" cloned in the scene. Run my code below and you will notice.
var UItecxt = GameObject.Find("#######COUNTER(Clone)");
var txtconvert : GUIText;
if(UItecxt != null)
txtconvert = UItecxt.GetComponent(GUIText);
else
Debug.Log("There was no GameObject with the name '#######COUNTER(Clone)' in the scene");
To fix it just make sure you do have a GameObject with that name.
Your question is not detail enough to determine the problem.
Still, i assumed the gameobject that you mentioned should be a prefab that you instantiated.
Where you put or attach the sciprt? Make sure it is attached to the prefab that you instantiated.
Also, you can try use direct reference the component instead of using gameobject.Find.
It is easier for you to drag and drop element at the inspector.