So i am currently starting to really get into game design and have a question: I currently have a spinning platform, but if i put an object or my player on it they dont get moved by the rotation! is there any simple way to make the other objects get turned too?
One way would be to react when an object hits your rotating platform and set it as a child of this.
private void OnTriggerEnter(Collider col)
{
col.transform.parent = transform;
}
private void OnTriggerExit(Collider col)
{
col.transform.parent = null;
}
Source
Related
I have a script for that Instantiates 2 game object but when something happens to one of them it also happens to the another one even when the conditions are not met for it. How can I make the script act separately for every Game Object?
GO script:
private Transform target;
public float speed = 2f;
private Animator anim;
public float H2Damage = 5f;
private healthBar Hp;
void Start()
{
target = GameObject.FindGameObjectWithTag("enemy").GetComponent<Transform>();
anim = gameObject.GetComponent<Animator>();
Hp = GameObject.FindGameObjectWithTag("enemy").GetComponentInChildren<healthBar>();
}
void Update()
{
target = GameObject.FindGameObjectWithTag("enemy").GetComponent<Transform>();
if (Hp.Died == true)
{
Hp.Died = false;
anim.SetBool("Hero2Attack", false);
anim.SetBool("Hero2Move", true);
}
if (!target || this.anim.GetCurrentAnimatorStateInfo(0).IsName("Hero2ATTACK"))
return;
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
anim.SetBool("Hero2Move", true);
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.CompareTag("enemy"))
{
anim.SetBool("Hero2Attack", true);
healthBar hp = col.transform.GetComponent<healthBar>();
hp.GiveDamage(H2Damage);
}
}
I believe they act the same way because they are getting the same GetComponentWithTag(), so they will Get the same objects. You also instantiate the animator, which is the exact same one, so they will do the same things. --> If it was as simple as changing the position by 1 meter per second, they would have different behavior (ie. be at different positions) But.... If you instantiate it, the current position is also instantiated, so you are going to have to get the current postion and set it to what you want, so both of these moving boxes aren't at the exact same position. You will have to do something similar here, you are going to want to either (create different scripts for the objects, or set the script values to different things)
TL;DR: You are copying the exact same script with the exact same components, so they will act similarly.
Fix: The only way to fix this is by setting their values after you instantiate them using GetComponent<>()or changing the script you assign them. (or any components for that matter)
Let me know if you have any problems or questions in the comments! :)
Context
I'm developing an AbstractAliveEntity, which have basically three functions:
Sight: Detect interactable objects. (Collider + Raycast)
Detection: Detect anothers AbstractAliveEntities (Collider + Raycast)
Hearing: Hear noises (Collider)
Currently i'm creating via script empty gameObjects with these colliders.
What i want
I want to know which collider was trigger in OnTriggerEnter and OnTriggerExit
Code
Creating the Sphere collider
private void Start() {
// Creating empty gameObject
sightGameObject = new GameObject("Sight");
sightGameObject.transform.parent = transform;
sightGameObject.transform.localPosition = new Vector3(0, 0, 0);
// Add Component Sphere
_sightInteractable = sightGameObject.AddComponent<SphereCollider>();
// _sightInteractable = gameObject.AddComponent<SphereCollider>();
_sightInteractable.radius = radiusInteractableDetection;
_sightInteractable.isTrigger = true;
}
Detecting
private void OnTriggerEnter(Collider other) {
// How can i detect which collider was?? this.gameObject = "Player" (i want "Sight")
}
Since Unity is originally designed around a component based approach my approach would be to split up the three separate "detection" systems into separate GameObjects with their own collider and script.
AliveEntity
SightController
ColliderA
DetectionController
ColliderB
HearingController
ColliderC
Then you can use the OnTrigger in each separate script to fire a notification to the main AbstractAliveEntity which then handles them on a case by case basis.
Main Script
OnSight(Collider other) {
// Do sight related actions here
}
OnDetection(Collider other) {
// Do detetction related actions here
}
OnHearing(Collider other) {
// Do hearing related actions here
}
Then for each respetive detector:
// reference to master script
public AbstractAliveEntity aae;
OnTriggerEnter(Collider other) {
// replace function with whatever you want to use
aae.OnSight(other)
}
The Added advantage here is that you are now also free to design 'blind' or 'deaf' Entities without all too much hassle. (You simply do not add the respective components)
other.gameObject to get the gameObject the other collider is attached to.
Check unity documentation about collider here for more info.
I created a dot following my mouse around in 2D and I created a cube object changing position on x and y. Now when I point my mouse to cube, it deactivates I set that, and now I want to activate it again. I try on trigger exit, but it didn't work.
public GameObject tapObject;
private float respawnTime = 1f;
public float xMin;
public float xMax;
public float yMin;
public float yMax;
void Start()
{
StartCoroutine(spawnEnemyTime());
}
private void RandomSpawnObject()
{
tapObject.transform.position = new Vector2(Random.Range(xMin, xMax), Random.Range(yMin, yMax));
}
private void OnTriggerEnter2D(Collider2D collision)
{
tapObject.SetActive(false);
}
IEnumerator spawnEnemyTime()
{
while (true)
{
yield return new WaitForSeconds(respawnTime);
RandomSpawnObject();
}
}
Once inactive the scripts on that object are not executed anymore => messages like OnTriggerExit are not called/executed.
One solution is to simply wrap the target object in a parent object and attach your script to the parent instead but make it (de)activate the child.
So the parent stays active and receives the message.
I am just going to repeat what everyone else here said:
A inactive object in Unity is truly inactive, meaning it does not receive any updates, can't collide with stuff and all the MonoBehaviour stuff that usually calls your code does not work either. You have to manually re-activate the object using a reference that you cached somewhere.
But, instead of just flat out disabling the whole object you could disable the components that you don't want to be active.
Example:
private void OnTriggerEnter2D(Collider2D collision)
{
tapObject.GetComponent<Renderer>().enabled = false;
}
private void OnTriggerExit2D(Collider2D collision)
{
tapObject.GetComponent<Renderer>().enabled = true;
}
This only deactivates your renderer component but leaves everything else as it is. So your object can still collide and it's still registered via e.g. OnTriggerExit.
Keep in mind that GetComponent<T>() is a pretty expensive operation so caching your component references is a good idea. The best solution would be to start out with a reference by creating a variable for it and assign it in the inspector.
Example:
//Set in inspector
public Renderer renderer
private void OnTriggerEnter2D(Collider2D collision)
{
renderer.enabled = false;
}
private void OnTriggerExit2D(Collider2D collision)
{
renderer.enabled = true;
}
When a GameObject is not active in Unity , you can't click it(no rendering,no colliding , nothing )
But ,You can create a hotkey (new script or in other script) , that can set it back to active , if it is not active.
public GameObject GO;
Use GO.setactive(true);
whereas gameobject is the object use to define the specific thing or object which needs to be active and the whole code needs to written in the method "spawnEnemyTime" so that it could be get active after the specific time period
You can just use an empty GameObject and get a reference the object that you want to enable/disable. If you get the reference before you disable it you will be able to activate it again.
the alternative is to do what TehMightyPotato said. Disable components it's actually the best way to solve this problem, but if you have lot's of components/subcomponents disable the gameobjects is faster.
I am coding a tower defense game in Unity, and I've ran into a snag while trying to figure out a way to place towers. My idea is to be able to click an art asset in the game when the player has a certain amount of points, and it replaces that art asset with a tower. Unfortunately, even when the player has the right amount of points, the object does not instantiate. I have made sure to link the prefab to the script, but it doesn't work. I'm stumped, the logic of the code seems right but maybe someone can help me figure out what's wrong here.
public class PointManager : MonoBehaviour
{
public int pointCount;
public Text pointDisplay;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
pointDisplay.text = "Points: " + pointCount;
}
}
public class PlaceTower: MonoBehaviour
{
public GameObject Tower;
private GameObject firstTower;
int placeCost = 25;
private PointManager pointsGained;
// Start is called before the first frame update
void Start()
{
pointsGained = GameObject.FindGameObjectWithTag("Point").GetComponent<PointManager>();
}
// Update is called once per frame
void Update()
{
}
private void OnMouseDown()
{
if (pointsGained.pointCount >= placeCost)
{
firstTower = Instantiate(Tower, transform.position, Quaternion.identity);
//Destroy(this.gameObject);
}
}
}
I got it. The problem was not with my code, but with my prefabs. In the documentation, I misread that OnMouseDown works on objects with colliders. While I had set up a circle collider on the object I was trying to instantiate, I had failed to put one on the object I was trying to instantiate from. Doing so fixed the problem immediately. A simple mistake that I would have completely glanced over had it not been for a second opinion. Thank you, Pac0!
I am trying to get a ball to pass trough an empty object but also send back a message to debug window. But I don't have a clue how to do this or where to start, so any help on this would be greatly appreciated. I am sorry I have no code to show as an example, however I have been able to get a collision detection or to allow the object pass through the empty object one at a time but never both. I have used OnTriggerEnter and OnCollionEnter.
Put a Collider (e.g. a SphereCollider) on your empty object, and set its Is Trigger to true. Now you can use OnTriggerEnter in your script (attached to the empty object) as you expected.
public class MyBehaviour : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
var collider = other.gameObject;
// Do something...
Debug.Log(collider);
}
}
You want to make your GameObject's collider a Trigger on the Editor. Go to the editor and add a collider to your GameObject, then make it a Trigger.
C# Code
void OnTriggerEnter(Collider other)
{
Debug.Log("I hit something: " + other.gameObject);
}
Javascript
function OnTriggerEnter (other : Collider)
{
Debug.Log("Hey I hit you: " + other.gameObject);
}