I'm trying to create objects that mark the cell that I can visit. I mark them with red square:
My code for creating objects:
using UnityEngine;
using System.Collections;
using System;
public class SpawnCheck : MonoBehaviour {
public GameObject checkObject;
public bool canSpawnCheck = true;
Vector2 boxSize;
public GameObject spawnedObject;
// Use this for initialization
void Start () {
Debug.Log("Into spawn check");
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Enter trigger collision");
canSpawnCheck = false;
if (other.gameObject.tag == "Target") {
Debug.Log ("Found Target");
}
if (other.gameObject.tag == "Wall") {
canSpawnCheck = false;
}
if (other.gameObject.tag == "Check") {
canSpawnCheck = false;
}
}
void OnTriggerExit2D(Collider2D other) {
Debug.Log("Exit trigger collision");
canSpawnCheck = true;
}
// Update is called once per frame
void Update () {
Debug.Log ("canSpawnCheck " + canSpawnCheck);
if (canSpawnCheck == true) {
Vector3 currentPosition = this.gameObject.transform.position;
Vector3 spawnPos = new Vector3 (Mathf.Round (currentPosition.x), Mathf.Round (currentPosition.y),0);
Debug.Log ("Physics.CheckSphere " + Physics.CheckSphere (spawnPos, 5));
if (!Physics.CheckSphere(spawnPos,5)) {
spawnedObject = (GameObject)Instantiate (checkObject, spawnPos, Quaternion.identity);
this.gameObject.GetComponentInParent<AILerp> ().possibleTargets.Add (spawnedObject);
}
}
}
}
My problem: as Physics.CheckSphere(spawnPos,5) always return false my code spawns too many red squares and spawn them upon each other. I want red squares to be created only once and never created on walls (white squares).
Your Check(Clone) GameObject has Box Collider 2D attached to it. Therefore every physics function you must use should be Physics2D.something not Physics.something. Notice the keyword there "2D".
If you use just Box Collider without the 2D in it, then you can use Physics.something. So, Physics.CheckSphere cannot be used with a 2D collider.
Check(Clone) is a SpriteRenderer, 2D Collider is appropriate. You just need to use one of the Physics2D overlap functions such Physics2D.OverlapBox, Physics2D.OverlapArea or Physics2D.OverlapCircle. Which ever one you prefer.
Related
My ideia basically is when i score i get 2 points, but when i touch a certain collider that changes to 3 and i am having a lot a trouble figuring out what colliders to use and how to use them.
I thnik i need to use another ontriggerenter
when i touch the cube it should change to 3
if (i touch a certain collider)
{
void OnTriggerEnter(Collider other)
{
ScoringSystem.theScore += 3;
}
}
else
{
ScoringSystem.theScore += 2;
}
First of all we need to create a GameManager to handle the Bool that checks if we are currently on the Line or not. We do this so we can acces it from all the scripts.
This code should be in a GameManager Object.
// Variable to check if the player is on the line or not
public bool stayingOnLine = false;
#region Singelton
public static GameManager instance;
void Awake()
{
if (instance != null) {
Debug.LogWarning("More than one Instance of GameManager found");
return;
}
instance = this;
}
#endregion
Then we add this Code to the GameObject that handles the LineCollider, to handle when the player enters the Line and when he leaves it. When this happens we change the Varible from the GameManager.
This code should be in your GameObject where the LineCollider that is set to IsTrigger is located.
GameManager gm;
void Start() {
gm = GameManager.instance;
}
void OnTriggerEnter(Collider col) {
// Player has entered the Line ColliderBox
if (col.CompareTag("Player Tag"))
gm.stayingOnLine = true;
}
void OnTriggerExit(Collider col) {
// Player has left the Line ColliderBox
if (col.CompareTag("Player Tag"))
gm.stayingOnLine = false;
}
After that we also need to add code to the GameObject that manages the HoopCollider. Because when the Ball enters we need to check if stayingOnline is true or false and then give different amount of points.
GameManager gm;
void Start() {
gm = GameManager.instance;
}
void OnTriggerEnter(Collider col) {
// Ball has entered the Hoop ColliderBox
if (!col.CompareTag("Ball Tag"))
return;
if (gm.stayingOnLine)
ScoringSystem.theScore += 3;
else
ScoringSystem.theScore += 2;
}
The problem is that I what to create an openable door. This door should open when the player enter the Box Collider which is connected to the door. But the problem is when the door begins to open and to rotate, Collider starts to rotate too which brings me a lot of problems with usind such an idea. I try to create EmptyObject with its Collider but I can't connect this Collider with script and OnTriggerEnter function itself. Maybe I don't understand something, who knows, I'm just a begginer. How knows how to help, please write an answer.
My code if somebody needs it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class openDoor : MonoBehaviour {
public Vector3 Rotation_;
private int i;
public float speed;
bool opentheDoor;
bool closetheDoor;
// Use this for initialization
void Start () {
opentheDoor = false;
closetheDoor = false;
}
// Update is called once per frame
void Update () {
if (opentheDoor == true) {
this.transform.Rotate (Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
opentheDoor = false;
i = 0;
}
}
if (closetheDoor == true) {
this.transform.Rotate (-Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
closetheDoor = false;
i = 0;
}
}
}
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player") { {
opentheDoor = true;
}
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.tag == "Player") {
closetheDoor = true;
}
}
}
This is how i would handle the scenerio
Take
DoorHandler.cs
public class DoorHandler : MonoBehaviour {
public Door door;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
door.OpenDoor();
}
}
}
This should be attached to Parent of the door.
Next Take
Door.cs
public class Door : MonoBehaviour {
public bool isOpened = false;
public void OpenDoor()
{
if (!isOpened)
{
isOpened = true;
Debug.Log("OPEN");
//OPEN DOOR CODE!
}
}
}
Attach this to the Door GameObject
NOTE
The hierarchy would be like DoorHandler->Door->DoorModel (where Door is just an empty gameobject pivot of the Door)
In DoorHandler GameObject attach BoxCollider and Check Mark IsTrigger.
Also Player SHOULD HAVE A RIGIDBODY (preferably Kinametic) and obviously a collider
So When Player enters the DoorHandler's Collider -> The DoorHandler's OnTriggerEnter will be triggered and finally Call the Door to OpenDoor()
Add another check in OnTriggerEnter that checks if the door is currently opening or not.
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player" && !opentheDoor) {
opentheDoor = true;
}
}
attach the door to an empty object. put the trigger on the empty object. then make the ontrigger entry rotate the door, not the paent object, and the collider will remain in place.
Parent
-child(door)
-child(collider)
using UnityEngine;
using System.Collections;
public class underWater : MonoBehaviour {
public float uwaterLevel=15f;
public Color normalColor;
public Color underWaterColor;
void Start () {
normalColor = new Color (0.5f,0.5f,0.5f,0.5f);
underWaterColor = new Color (0.22f,0.65f,0.77f,0.5f);
}
void Update () {
Debug.Log (uwaterLevel);
Debug.Log (transform.position.y);
if(Camera.main.transform.position.y<uwaterLevel){
Debug.Log("Underwater Update");
setUnderWater();
}else{
Debug.Log("Normal Update");
setNormal();
}
}
public void setUnderWater(){
Debug.Log("Under Water");
RenderSettings.fog = true;
RenderSettings.fogDensity = 0.05f;
RenderSettings.fogColor = underWaterColor;
}
public void setNormal(){
Debug.Log("Normal");
RenderSettings.fog = true;
RenderSettings.fog = false;
RenderSettings.fogDensity = 0.003f;
RenderSettings.fogColor = normalColor;
}
}
How can I detect if my character is under water? Water is above the ground(a lake between the hills) so I can't use negative Y-axis. I'm using FPSController from Unity Standard Assests.
Make a large Collider the size of the water. Make it a trigger. Make it's tag "Water"
public void OnTriggerEnter(Collider col)
{
if(col.tag == "Water")
{
// In water
}
}
public void OnTriggerStay(Collider col)
{
if(col.tag == "Water")
{
// In water
}
}
public void OnTriggerExit(Collider col)
{
if(col.tag == "Water")
{
// Exit water
}
}
I'm posting an answer rather than a comment since I can't comment yet.
Similar to what Andrew said, to prevent your game from thinking you're underwater as soon as your character puts its foot in the water, You could add an empty gameobject a few centimeters above your character's head and put a collider on that.
Then use Andrew's logic to determine that your character is underwater.
I have a very annoying bug, and I can't get rid of it.
The situation is, that I have a parent with the following script attached, and a trigger box2d collider. It has a child, with a rigidbody2d(kinematic, gravity=0, freeze position x, and rotation z), a sprite renderer and a polygon collider (with 4 edges).
My problem is, when the scene is loaded, sometimes my child objects (always random how much of them and which ones), jumps to transform.position 0,0,0.
I link the script, that is attached to the parent
using UnityEngine;
using System.Collections;
public class FallingSpikeHazard : MonoBehaviour
{
public GameObject spike;
private Rigidbody2D spikeRigidbody;
[SerializeField]
private Vector3 startPosition;
void Awake ()
{
startPosition = spike.transform.localPosition;
}
void Start ()
{
spikeRigidbody = spike.GetComponent<Rigidbody2D> ();
Helper.JustReset += ResetMe;
Invoke ("CheckPosition", Time.deltaTime);
}
void CheckPosition ()
{
if (spike.transform.localPosition != startPosition) {
Debug.LogError ("t1" + spike.transform.localPosition);
spike.transform.localPosition = startPosition;
Debug.LogError ("t2" + spike.transform.localPosition);
}
}
void OnDestroy ()
{
Helper.JustReset -= ResetMe;
}
void ResetMe ()
{
spikeRigidbody.gravityScale = 0;
spikeRigidbody.isKinematic = true;
if (startPosition != Vector3.zero) {
spike.transform.localPosition = startPosition;
}
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag.Equals ("Player")) {
spikeRigidbody.isKinematic = false;
spikeRigidbody.gravityScale = 1;
}
}
}
Events are not called, in other hand, if I disable the script, it keeps happening. Nothing have reference to these GameObjects. I don't have animations, or animator attached.
What could cause my problem?
You need to have a Rigidbody2D component in the parent GameObject in order for the OnTriggerEnter function to be called.
I would like to make a gameobject in my game, which when enter trigger, then it will teleport my character to an another position (otherTeleport.transform.position), however when I use the script what I have written, my character won't teleport there, while the enemy will. If I put a Debug.Log in the bounce script which will log the character's position I see that my character has been at the otherTeleport's position, but only for one debuglog, and after that it's back to the original teleport's position. The teleport's would be working two-way so if the user go to one it will port it to the second, and if he goes to the second, then it will be ported to the first.
Here is my code:
public class TeleportScript : MonoBehaviour {
public GameObject otherTeleport;
private Collider otherTeleportColl;
public bool isNeedToTeleport;
private TeleportScript otherTeleportScript;
private GameObject player;
private Bounce bounceScript;
// Use this for initialization
void Start () {
isNeedToTeleport = true;
otherTeleportColl = otherTeleport.GetComponent<Collider>();
otherTeleportScript = otherTeleport.GetComponent<TeleportScript>();
player = GameObject.Find("Player");
bounceScript = player.GetComponent<Bounce>();
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider collider) {
if (isNeedToTeleport == true) {
if (collider.tag == "Enemy") {
otherTeleportScript.setNeedToTeleport(false);
collider.transform.position = otherTeleport.transform.position;
}
if (collider.tag == "Player") {
otherTeleportScript.setNeedToTeleport(false);
bounceScript.player.transform.position = otherTeleport.transform.position;
collider.transform.position = otherTeleport.transform.position;
bounceScript.playerTransform.position = otherTeleport.transform.position;
}
}
}
void OnTriggerExit(Collider collider) {
Debug.Log ("TELEPORTED OUT");
setNeedToTeleport(true);
otherTeleportScript.setNeedToTeleport(true);
}
public void setNeedToTeleport(bool value) {
if (value == true) {
isNeedToTeleport = true;
}
else {
isNeedToTeleport = false;
}
}
}
Any help would be appreciated!
I did some changes to your code, can't test it because I don't have access to unity right now, let me know if it works...
public class TeleportScript : MonoBehaviour {
public GameObject otherTeleport;
private Collider otherTeleportColl;
public bool isNeedToTeleport;
private TeleportScript otherTeleportScript;
private GameObject player;
private Bounce bounceScript;
// Use this for initialization
void Start () {
isNeedToTeleport = true;
otherTeleportColl = otherTeleport.GetComponent<Collider>();
otherTeleportScript = otherTeleport.GetComponent<TeleportScript>();
player = GameObject.Find("Player");
bounceScript = player.GetComponent<Bounce>();
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider collider) {
if(collider.tag == "Player" && isNeedToTeleport)
{
otherTeleportScript.setNeedToTeleport(false);
collider.transform.position = otherTeleport.transform.position;
bounceScript.player.transform.position = otherTeleport.transform.position; //not sure what is this for....
}
}
void OnTriggerExit(Collider collider) {
Debug.Log ("TELEPORTED OUT");
setNeedToTeleport(true);
otherTeleportScript.setNeedToTeleport(true);
}
public void setNeedToTeleport(bool value) {
if (value == true)
isNeedToTeleport = true;
else
isNeedToTeleport = false;
}
}
Your character teleports to the other place
after that you move the collider over there aswell, notice that the collider's object of other script of teleportation has been initialized with the isNeedToTeleport = true;
The character now also bounces there, hits the collider of the other object, it checks that isNeedToTelport is in fact true in this other script and it goes into the same If condition and teleports back!
Take this line:
otherTeleportScript.setNeedToTeleport(true);
out of your OnTriggerExit, or set it to false. Actually setting it to false might be better. You want to tell the other script that someone is incoming and it shouldn't immediately teleport them back.
As an aside, you should change your setNeedToTeleport function to this:
public void setNeedToTeleport(bool value) {
isNeedToTeleport = value;
}
Those ifs are redundant.