How do I call OnTriggerEnter multiple times in unity? - unity3d

I have to push a button (inside a medical patient) multiple times, with OnCollisionEnter(); the problem is that it collides with the patient's mesh and the animations are always triggered, which is not good for me. With OnTriggerEnter(), it works fine as it is a trigger and does not collide with the medical patient's mesh, only with my avatar, which uses hand tracking. I want to call OnTriggerEnter() multiple times. I thought about instantiating the asset again, then destroying the first asset, but I have not gotten any luck. Please help! The following code is attached to my buttons inside the patient, which is to be palpated. How can I trigger OnTriggerEnter multiple times?
private void OnTriggerEnter(Collider other)
{
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 1)
{
palpation_patient.animator.SetLayerWeight(1, 1);
}
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 2)
{
palpation_patient.animator.SetLayerWeight(2, 1);
}
if (palpation_patient.animation_selection == 6 && palpation_patient.pain_level == 3)
{
palpation_patient.animator.SetLayerWeight(3, 1);
}
}

Related

Keeping variable from changing on another scene load

I'm new to unity and i'm trying to load scenes based on items collected.
Problem is that the counter is not counting my acquired items.
I'm using OnTriggerEnter2D() to trigger the event; Below is the snippet:
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("Player"))
{
collectionNumber += 1;
Destroy(gameObject);
if (collectionNumber == 1)
{
collision.gameObject.transform.Find("Acquired_Items").GetChild(0).gameObject.SetActive(true);
qiCollector.gameObject.transform.GetChild(0).gameObject.SetActive(true);
}
else if (collectionNumber == 2)
{
collision.gameObject.transform.Find("Acquired_Items").GetChild(1).gameObject.SetActive(true);
qiCollector.gameObject.transform.GetChild(1).gameObject.SetActive(true);
}
else if (collectionNumber == 3)
{
collision.gameObject.transform.Find("Acquired_Items").GetChild(2).gameObject.SetActive(true);
qiCollector.gameObject.transform.GetChild(2).gameObject.SetActive(true);
}
else
{
Debug.LogWarning("All Items Collected !!");
}
cN.text = "Collection Number " + collectionNumber.ToString();
}
}
Whenever a new scene is loaded this script is loaded because it is on my quest item. And for every scene there is a quest item. So what I want to do is basically keep track of my collectionNumber, but it resets to 0.
Any help is much appreciated :)
First method:
Don't allow your object to be destroyed on scene load
https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html
public static void DontDestroyOnLoad(Object target);
Above code will prevent destroying your GameObject and its components from getting destroyed when loading a new scene, thus your script values
Second Method:
Write out your only value into a player pref
https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
// How to save the value
PlayerPrefs.SetInt("CollectionNumber", collectionNumber);
// How to get that value
collectionNumber = PlayerPrefs.GetInt("CollectionNumber", 0);
Third method:
Implement a saving mechanism:
In your case i would not suggest this

How to transfer a VR button ownership using Photon2?

I am currently working on a project and I want to use several buttons in my multiplayer game.
Unfortunately the button can only be pushed locally and it's not synced over the network.
For some reasons the game doesn't trigger the script that should transfer the ownership to the player
I don't really know what's going on and why this isn't triggered ...
I already tried to ad photon tranform views on the moving part and the button itself but without results
private void OnTriggerEnter(Collider other)
{
if(other.name == "LHand" || other.name == "RHand")
{
ChangeOwnership(other);
}
print("trigger entered but not a hand");
}
public void ChangeOwnership(Collider col)
{
if (GetComponent<PhotonView>().Owner != col.GetComponent<PhotonView>().Owner)
{
GetComponent<PhotonView>().TransferOwnership(col.GetComponent<PhotonView>().Owner);
print("changed ownership to: " + col.GetComponent<PhotonView>().Owner);
}
}
If the trigger is actually entered this should show the player as the owner and not the scene...
So if someone has a clue about this I'll take it ...

Unable to destroy gameObject?

I am trying to destroy a gameObject once it has collided with two other objects with the following code but it does not work.
void OnCollisionEnter(Collision col)
{
if (col.gameObject.tag == "Sphere" && col.gameObject.tag == "Pyramid")
{
Destroy (GameObject.FindWithTag("Pentagon"));
}
}
Can someone offer a correction of my code because I can't seem to figure out how to destroy my "Pentagon"?
The problem is in your first line:
if (col.gameObject.tag == "Sphere" && col.gameObject.tag == "Pyramid")
You cant have 2 tags on a gameObject. I assume what you want to say is || instead of &&.
What are you trying to achieve in that second block of code? Instead of deleting the rigidbody, maybe just set RigidBody.Enabled = false.

Overlapping Collider2D Triggers

Ok lets get into it.
I've got 2 colliders whose purpose it is to determine the hit type of the ball. If it is GoodHit or NiceHit (Nice is like Perfect).
The GoodHit collider2d has a much larger area than NiceHit.
The NiceHit on the other hand overlaps to a portion of GoodHit in its center.
Using this code I can determine whether the ball enters the area of GoodHit and NiceHit
void OnTriggerEnter2D(Collider2D other) {
if (other.name == "HitNice") {
hitType = 2;
} else if(other.name == "HitGood") {
hitType = 1;
}
}
void OnTriggerStay2D(Collider2D other) {
if (other.name == "HitNice") {
hitType = 2;
} else if(other.name == "HitGood") {
hitType = 1;
}
}
void OnTriggerExit2D(Collider2D other) {
hitType = 0;
}
The problem is it doesn't triggers the NiceHit and the hitType is still valued 1 regardless if the ball is in NiceHit area.
I first created the Goodhit object, that in a sense gives it a priority than NiceHit. I could swap them by names and values that way I can achieve the thing that I wanted but that doesn't really solved it.
Any workaround or tweaks I can do? Thanks!
You have two overlapping triggers, one of which is in the middle of a larger trigger.
Here's something to remember: if an object is inside the inner trigger, it is also inside the larger trigger!
So in your code, you use OnTriggerStay to determine if the object is in one of those triggers. Let's take a look at that:
void OnTriggerStay2D(Collider2D other) {
if (other.name == "HitNice") {
hitType = 2;
} else if(other.name == "HitGood") {
hitType = 1;
}
}
This function is executed once per trigger that the object is inside of. So this function is executed twice if it is inside of the HitNice trigger. So let's say Unity calls this function for each trigger. What is probably happening is that it's calling the handlers in a bad order (pseudocode):
OnTriggerEnter(HitNice) //hitType is 2
OnTriggerEnter(HitGood) //hitType is now 1!
Unity is calling the collider handlers from inside out, causing the result from a HitGood trigger to always override the HitNice value. I don't know for sure if that's how it works, but looking at your code it's totally a possibility of why it's not working correctly.
Now, I can't say this for sure, but I think just using your OnTriggerEnter handler will suffice. It will only trigger the hitType detection when it enters a collider rather than when it stays. Since the object must enter the outer trigger before entering the inner trigger, this means that it should always evaluate in the correct order. In that case, your code is probably working as is, but I would say that your logic should be like this:
void OnTriggerEnter2D(Collider2D other) {
if(other.name == "HitNice") {
hitType = 2;
} else if(other.name == "HitGood" && hitType != 2) {
hitType = 1;
}
}
The only caveat of this approach is that you would need to reset the value of hitType manually. Not sure exactly how your game works, but this should give you an idea of how to approach this. Your HitNice should always override a HitGood. So when OnTriggerEnter is called for HitGood, check that you haven't yet hit HitNice yet. Or even better, record both hit types in separate variables, and then resolve which type of hit it was later on when doing scoring or whatever.

touch.phase == TouchPhase.Canceled not worked

I'm tired to handle and solve issues related to multitouch. I'm using maximum 5 touches simultaneously but when two touches are down on two objects and I moved my fingers then that both touches fired TouchPhase.Ended event but not TouchedPhase.Canceled.
I want to fire TouchPhase.Canceled when my fingers are out of those objects.
if (touch.phase == TouchPhase.Began) {
hitObject.GetComponent ().TouchDown (hitObject);
}
if (touch.phase == TouchPhase.Ended) {
hitObject.GetComponent ().TouchExit (hitObject);
}
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary) {
hitObject.GetComponent ().TouchStay (hitObject);
}
if (touch.phase == TouchPhase.Canceled) {
print ("Touched canceled....");
hitObject.GetComponent ().TouchExit (hitObject);
}
If i understand your comment correctly
Look,I have one object on my screen.I use raycast for detecting that object.in hitObject i m stored that hittedObject and when my fingure touchdown on that object then it works. if i touchup my fingure from that hitted object that is also worked.when my fingure is stayed on that object or i m move my fingure on that hitted object that is also worked. but when during moving my fingure if it is move outside that object at that time TouchPhase.Canceled event should be fired. but that can not worked . That is my issue. How can i solved it ?
and
I want to stop dragging/swapping finger (not moving) on that hitted object how can i do?
you are going to have to restrict the swiping based on the touch position.
var realWorldPos = Camera.main.ScreenToWorldPoint(touch.position);
if(realWorldPos.x < maximumXSwipePosition && realWorldPos.x > minimumXSwipePosition)
{
//do the stuff you want to do
}
//otherwise, don't do it.