I don't know how to communicate with other scripts - c#

I have a Player script. I have the variables on there
public class Player : MonoBehaviour
{
float horimove;
Rigidbody rb;
public float speed;
public GameObject thrown;
public bool win;
On my other script (I'm making a game where you instantiate spheres into a hole and win.)
public class spheresciprt : MonoBehaviour
{
public Player pscript;
public GameObject player;
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("Player");
pscript = player.GetComponent<Player>();
}
private void OnTriggerEnter(Collider other)
{
if (gameObject.CompareTag("win"))
{
pscript.win = true;
}
}
However pscript.win doesn't change. The bool always stays false but I want the player to win after the sphere hits the trigger in the hole I want it to go to. I tried different computers. The same thing happened in different games I think so I'm probably just missing something.

First of all, make sure that the collision is detected. You can easily do something like
void OnTriggerEnter()
{
Debug.Log("Pass1");
if (gameObject.CompareTag("win"))
{
Debug.Log("Hey, it worked!");
}
}
in the OnTriggerEnter to check that.
If the collision is NOT detected, make sure there are colliders on all the affected GameObjects, as well as a RigidBody component on the sphere. Also, make sure that the collider is marked as Trigger. If you still have an issue with that, we will need to see your inspector to figure it out.
If the collision IS detected... Well, start by making sure that you have assigned the proper tag on the hole. Then, make sure that the player GameObject is actually called "Player" (since you are trying to find it by name) and that it has the script you are trying to get on the object you actually find (and not on one of its children). I hope that works, because I can't see anything else seriously flawed at your code.

Have you tried to change
if (gameObject.CompareTag("win"))
to
if (collider.gameObject.CompareTag("win"))
or just add the rigidbody to both player and other object.
does the other object have "win" tag?

Here is your script:
public class spheresciprt : MonoBehaviour
{
public Player pscript;
public GameObject player;
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("Player");
pscript = player.GetComponent<Player>();
}
private void OnTriggerEnter(Collider other)
{
if (gameObject.CompareTag("win"))
{
pscript.win = true;
}
}
}
It sets pscript to the current values in Player script. This is the problem, because it is setting a variable to the current values, and you want access to the component. You could change this by, just replace all of the pscript variables with player.GetComponent<Player>(). There are other ways of doing this. You could, at the end of OnTriggerEnter, add this:
void OnTriggerEnter(Collider other)
{
...
player.GetComponent<Player>() = pscript;
}
In both of these solutions you fix it. In one, you re-apply the variable. In the other, you are changing the component directly. Which is what you want, because you have pscript as an instance of player script, not the player script that is attached to player.

Related

I am trying to detect if I am colliding with a specific object in unity

In my scene, there are multiple objects with the same layer and tag. I have a variable that will be set to the gameobject for one of these objects. I would like to do something when I collide with the object that is set to the variable.
My current code is:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.otherCollider == targetFood)
{
Debug.Log("I am touching food");
}
}
I've tried a few different methods of checking if it is touching the food, but none have worked. Help would be appreciated!
If you get the game object from the collision, you should be able to determine if the target food has been touched.
using UnityEngine;
public class Example : MonoBehaviour
{
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject == targetFood)
{
Debug.Log("I am touching food");
}
}
}
This is assuming that targetFood is a variable that is of type GameObject.

OnTriggerEnter() is called right on the start

I'm making some sort of a Evolution simualtor game. I have a script that is supposed to destroy the GameObject it's attached to when a creature's CapsuleCollider Triggers the OnTriggerEnter().
I have a problem that even tho the Creature's collider isn't even close to the Food, it still destroys the GameObject.
My script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FoodEat : MonoBehaviour
{
public GameObject FoodGO;
public Rigidbody FoodRB;
private void OnTriggerEnter(Collider Creature)
{
Destroy(FoodGO);
}
void Start()
{
FoodRB = GetComponent<Rigidbody>();
FoodGO = FoodRB.gameObject;
}
void Update()
{
Rigidbody[] allRigidBodies = (Rigidbody[])FindObjectsOfType(typeof(Rigidbody));
foreach (Rigidbody body in allRigidBodies)
{
if (body.gameObject.layer == 10)
{
OnTriggerEnter(body.gameObject.GetComponent<CapsuleCollider>());
}
}
}
}
OnTriggerEnter is a monobehaviour lifecycle method. You should not call it from your own code; it will automatically be called when it detects collisions.
Furthermore, the logic in your code right now seems to be incorrect, it is...
"Every frame, loop through all rigidbodies in the scene and if 1 is found on layer 10, destroy the FoodGO"
Simply remove your entire Update method and put an if in your Collision method, and it should work:
[RequireComponent(typeof(Rigidbody), typeof(Collider))]
public class FoodEat : MonoBehaviour
{
private void OnTriggerEnter(collider other)
{
Debug.Log(other.gameObject.name + " on layer " + other.gameObject.layer);
if (other.gameObject.layer == 10)
Destroy(this.gameObject);
}
}
A few noteworthy edits of your code:
I removed FoodGO, since it's the GameObject this script is attached to, you can access it by just writing gameObject or this.gameObject.
I remove the Rigidbody reference since it is not used anymore, and thus the entire Start() method.
Since this code requires a Rigidbody and a Collider to work, I added a [RequireComponent] attribute in the top, which will make Unity tell you if you forgot to add those components on the object you attach this script to.
I added a Debug.Log that prints the name & the layer on the creature that collides with the food, so you can debug and make sure it is working as expected

How to tell which of the colliders has been collided?

I'm creating a game in which there are enemies, I want to have headshots in the game so I have 2 colliders: one to the head and one to the body. I can't find any good way to tell which is which in the code.
I thought of a solution but I don't like it- a different type of collider to the head, and different type to the body (like polygon and box colliders). It works but I don't think it's good enough (if I want to add more colliders or have two of the same type that wouldn't work).
virtual protected void OnTriggerEnter2D(Collider2D collider2D)
{
if (collider2D.gameObject.tag.Equals("Zombie"))
{
Destroy(gameObject);//destroy bullet
Zombie zombie = collider2D.gameObject.GetComponent<Zombie>();
if (collider2D is BoxCollider2D)
zombie.HeadShot(demage);//headshot
else zombie.BulletHit(demage);//normal hit
}
}
I want a way to tag the colliders somehow so I can tell between them.
You need to create public variables of type BoxCollider2D and assign your colliders. When a collision occurs call an IF statement inside of OnTriggerEnter to see which one has collided. This will work no matter if there are more of the same types of collider.
public class Example : MonoBehaviour
{
public BoxCollider2D box01;
public BoxCollider2D box02;
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.IsTouching(box01))
{
Debug.Log("1");
}
else if(collision.IsTouching(box02))
{
Debug.Log("2");
}
}
}
isTouching is a Unity method which returns a bool depending on a collider that is comparing.
I would suggest to not add all colliders on the same GameObject but rather give each collider it's own child GameObject (this way you also can see easily which colliders belongs to which outline in the scene view ;) )
Then you could use a class with an enum to define which type of collider you have there:
public class BodyPart : MonoBehaviour
{
public BodyPartType Type;
}
public enum BodyPartType
{
Head,
LeftArm,
RightArm,
Body,
LeftLeg,
RightLeg
}
and attach it to all body parts next to each collider.
Then you could do something like
virtual protected void OnTriggerEnter2D(Collider2D collider2D)
{
if (collider2D.gameObject.tag.Equals("Zombie"))
{
Destroy(gameObject);//destroy bullet
// Note you then should use GetComponentInParent here
// since your colliders are now on child objects
Zombie zombie = collider2D.gameObject.GetComponentInParent<Zombie>();
var bodyPart = collider2D.GetComponent<BodyPart>();
switch(bodyPart.Type)
{
case BodyPartType.Head:
zombie.HeadShot(demage);//headshot
break;
// you now could differ between more types here
default:
zombie.BulletHit(demage);//normal hit
break;
}
}
}

Player Respawn and Death when falling

I'm going through the worse struggle right now. I'm trying to create a game with pitfalls that if the players fall through, they respawn and the game counts their death. I'm completely at wit's end and don't know where to even start with this. The game is 3D
using UnityEngine;
using System.Collections;
public class Respawn : MonoBehaviour {
public Transform spawnPoint;
public float minHeightForDeath;
public GameObject player;
void Start () {
}
// Update is called once per frame
void Update () {
if (player.transform.position.y < minHeightForDeath) {
player.transform.position = spawnPoint;
}
}
}
Use a collider on a plane/cube/whatever works for you, and set it to be a trigger. So when they pass through the trigger collider, it can record them and do what you want with it.
Use the OnTriggerEnter method script
void OnTriggerEnter(Collider other)
{
other.transform.position = spawnPoint.position;
}
You are not putting any data in the "minHeightForDeath" float. Unless you do it in the editor.
Other than that, have you put the script on the player gameObject? And have you set what you have to in the editor?

Editing variables with GetComponent C#

I am trying to get a conveyor belt to reverse its direction when the player presses a button.
Here's the code for the conveyor belt
using UnityEngine;
using System.Collections;
public class Conveyor : MonoBehaviour {
public float speed = 1.0f;
void OnTriggerStay(Collider col)
{
col.transform.position += transform.forward * speed * Time.deltaTime;
}
}
And the code for the button
public class PushButton : MonoBehaviour
{
public GameObject Button;
private Conveyor conveyor;
void Awake ()
{
conveyor = GetComponent<Conveyor>();
}
void OnTriggerStay(Collider entity)
{
if (entity.tag == "Player")
{
if (Input.GetKeyUp(KeyCode.E))
{
conveyor.speed = conveyor.speed * -1;
}
}
}
}
I'm getting an error saying "Object Reference not set to the instance of an object PushButton.OnTriggerStay (Unity Engine.Collider entity) (at Assests/PushButton.cs21)
I'm still not very familiar with using getComponent so I'm not sure how to fix this. Any help would be appreciated.
GetComponent will need a reference to an initialized object and a component or class that object has assigned. For what you are wanting, you will want to find a game object in the scene. Because you are already specifying that your GameObject has a Conveyor class assigned to it, find your GameObject and then specify the Conveyor component.
void Awake ()
{
conveyor = GameObject.FindWithTag("Conveyor").GetComponent<Conveyor>();
}
This should do the trick pending you have tagged your Conveyor game object with a 'Conveyor' tag.
However, there is an even easier way to quickly "grab" something like this. Be careful though!
void Awake()
{
conveyor = Object.FindObjectOfType<Conveyor>();
// ONLY DO THAT IF THERE IS ONLY >>ONE<< OF THE THING!
}
Here's a little essay on that. http://answers.unity3d.com/answers/46285/view.html
You often do that for example to find "boss" objects .. scene managers and the like.
Don't forget though, you can always just use a public variable, and drag inteh Inspector - that's always a sound idea for beginners working with Unity.

Categories

Resources