Unity Fungus Flowchart doesn't receive message with my script - unity3d

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.

Related

Unity comparing gameobjects

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.

unity collision doesnt work, what is the problem in my code?

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

How would I detect if my player is touching a game object?

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.

Unity: OnCollisionEnter fires only on NEW entry, but not on NEW entry on different object with same name

I am building a platformer with appearing boxes. The box gets rendered as soon as the player hits it hitbox. This works just fine like so:
public class AppearingBoxes : MonoBehaviour
{
public GameObject Block, RageFace;
bool showBlock = false;
void Start()
{
showBlock = false;
}
void OnCollisionEnter(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
void FixedUpdate()
{
Block.GetComponent<Renderer>().enabled = showBlock;
RageFace.GetComponent<Renderer>().enabled = showBlock;
}
}
This script is attached to all of those boxes. Each box is an individual box but all with the same script and properties and name:
But here comes the issue. Only the first HIT triggers a box. As you can imagine, the player jumps on top of those invisble boxes and then triggers the one he hits. The player now moves forward over the other boxes that are still invisble and enters there hitboxes. However they dont appear. I believe this is due to the fact that the player is still in the "same" hitbox even though it is a different prefab object. If I jump ontop of the invisible platform and then fall back down to it (i left and then reentered the trigger) the box on which I land immeadiately appears as it should.
So what can I do to get the box to appear as soon as the player touched it even though he is has not left the hitbox of the box before?
Thank you! :)
Try to change the boxes colliders to isTrigger and use instead OnTriggerEnter2D
Or maybe it's because you use OnCollisionEnter instead of OnCollisionEnter2D ?
There is a problem in your code. I don't know if you missed that or it is a typo but you can not use OnCollisionEnter with a Collision2D parameter. Your game would run but it must be giving you this error message:
Script error: OnCollisionEnter
This message parameter has to be of type: Collision
The message will be ignored.
Use OnCollisionEnter2D instead
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
Everyone, I did find a "workaround" It sill doesnt really explain the issue but alreast works...
What I did was to increase the size of the BoxCollider for every box just a little bit more. Like 3 pixels bigger than the actual box the player stands on. This solved the issue but makes me wonder: If the player didnt "really" collide with the collider in the first place he wouldve fallen through. But he didnt. Now the colliders a slightly bigger and everything gets triggered just perfect. Maybe a bug in the engine?
Thanks for all your help
He didn't fall because the collider isn't Trigger that's all.

How to disable a collider when the trigger of another collider has been entered?

I am building a game where the player runs on a path. When the player triggers a collider, 2 enemy objects will spawn.
What I want is when the first collider trigger has been entered, I want the second collider, which is at a certain distance from the first collider, to get disabled for a certain time. How to achieve this?
If you'd like to disable the colliders so they won't hit or rebound off the wall, for example, then you can change your collider's "isTrigger" variable to true, to change it into a trigger volume instead of a solid collider. This has the effect of disabling it - in that it won't cause other objects to stop or rebound if they hit it.
For example:
function Update() {
if (Input.GetKeyDown(KeyCode.X)) {
collider.isTrigger = true;
}
}
Note that things like MouseOver still work.
If you want to disable that completely, you can try collider.enabled = false. I'm not sure if that works or not. If it doesn't, you can always scale down your collider:
var myOldSize:Vector3;
function DisableBoxCollider(myCollider:BoxCollider)
{
//actually just resizes it
myOldSize=myCollider.size;
myCollider.size=Vector3(0,0,0);
}
function EnableBoxCollider(myCollider:BoxCollider)
{
if(myOldSize!=Vector3(0,0,0))
myCollider.size=myOldSize;
}
You can use the above code to integrate it in your own project. I'm not going to spill out all of the code for you because else we'd miss the point of learning to program and post on Stackoverflow in general. But it should help you to get on your way. Try and play some with the code, and if you have questions, get back here and ask them, providing the question with some code to show what you have tried.