I have created a random generator for a prefab called "Tunnel". Whenever i collide with a tunnel prefab, i wish to keep the game running. If i am no longer colliding with a tunnel i wish the game to stop.
The game works fine for the first tunnel, but when i reach the end of the first tunnel (start of the second - they overlap), my "OnTriggerExit2D" function stops the game.
Is there a way to tell my "OnTriggerExit2D" to check if i'm colliding with a different tunnel?
Here's my code:
void OnTriggerEnter2D(Collider2D other)
{
Debug.Log (other.gameObject.tag);
if (other.gameObject.CompareTag ("LeftTunnel")) {
touchRef.onTunnelL = true;
}
if (other.gameObject.CompareTag ("RightTunnel")) {
touchRef.onTunnelR = true;
}
}
void OnTriggerExit2D(Collider2D other)
{
if(other.gameObject.CompareTag("LeftTunnel"))
{
touchRef.OnTriggerExit2Dchild();
touchRef.onTunnelL = false;
}
if(other.gameObject.CompareTag("RightTunnel"))
{
touchRef.OnTriggerExit2Dchild();
touchRef.onTunnelR = false;
}
}
thanks!
So, after consulting with some people I decided to change the whole mechanism to work with ray casting and it works great now.
Here's the code for anyone in the future (I call cast function on Update):
void Cast()
{
for (int i = 0; i < Input.touchCount; ++i)
{
Vector2 test = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
RaycastHit2D hit = Physics2D.Raycast(test, (Input.GetTouch(i).position));
Vector2 touchPos = new Vector2(test.x, test.y);
onLeft(touchPos);
onRight(touchPos);
}
}
void onLeft(Vector2 touchPos){
Collider2D tempL;
if (tempL = Physics2D.OverlapPoint (touchPos)) {
if(tempL.CompareTag("LeftTunnel")){
Debug.Log ("Hit Left tunnel");
onTunnelL = true;
}
}
else{
onTunnelL = false;
}
}
void onRight(Vector2 touchPos){
Collider2D tempR;
if (tempR = Physics2D.OverlapPoint (touchPos)) {
if(tempR.CompareTag("RightTunnel")){
Debug.Log ("Hit Right tunnel");
onTunnelR = true;
}
}
else{
onTunnelR = false;
}
}
Related
So I'm trying to implement shooting in a multiplayer game. I want to spawn a bullet out of a weapon. On the server side it works, but as I shoot as a client it says [Netcode] Behaviour index was out of bounds. Did you mess up the order of your NetworkBehaviours?.
The bullet is a prefab which I included in NetworPrefabs. The prefab also has a Network Object component.
This is where I call shoot()
if(shot == false && transform.GetChild(0).GetComponent<Weapon>().bulletInMag > 0 && reloading == false)
{
shot = true;
StartCoroutine(shoot());
}
This is what shoot() does
IEnumerator shoot()
{
firePoint = transform.GetChild(0).GetChild(0).transform;
weapon = transform.GetChild(0).gameObject.GetComponent<Weapon>();
if (weapon.threeShot)
{
for(int i=0; i<3; i++)
{
if(NetworkManager.Singleton.IsServer)
{
spawnBullet();
} else
{
spawnBulletServerRpc();
}
weapon.bulletInMag -= 1;
SharedFunctions.Instance.updateAmmoCount();
yield return new WaitForSeconds(0.2f);
}
yield return new WaitForSeconds(weapon.shootingIntervall);
shot = false;
}
else
{
if (NetworkManager.Singleton.IsServer)
{
spawnBullet();
}
else
{
spawnBulletServerRpc();
}
weapon.bulletInMag -= 1;
SharedFunctions.Instance.updateAmmoCount();
yield return new WaitForSeconds(weapon.shootingIntervall);
shot = false;
}
}
void spawnBullet()
{
GameObject bullet = Instantiate(prefabBullet, firePoint.position, transform.rotation);
bullet.GetComponent<Rigidbody2D>().AddForce(firePoint.up * weapon.bulletSpeed, ForceMode2D.Impulse);
bullet.GetComponent<NetworkObject>().Spawn();
}
[ServerRpc]
void spawnBulletServerRpc()
{
spawnBullet();
}
I'm thankful for any help.
I finally fixed the issue. The error [Netcode] Behaviour index was out of bounds. Did you mess up the order of your NetworkBehaviours? basically means that there is a mismatch between server and client representation of a network object.
At the beginning of my Player script I wrote:
public override void OnNetworkSpawn()
{
if (!IsOwner) Destroy(this);
}
which deletes the component if your not the owner.
So when I joined I had the script on client side but it wasn't there on server side. So when I tried to make an ServerRpc it didn't know where to send it. The same goes for ClientRpc.
A very helpful source was the Unity Mulitplayer Networking Discord: https://discord.gg/buMxnnPvTb
This is the code that I have on my player script:
void OnTriggerEnter2D (Collider2D collider2D)
{
if (collider2D.gameObject.tag == "powerup")
{
PoweredUp = true;
PowerupTimer = PowerupTimer;
PowerupTimer -= Time.deltaTime;
}
}
...and this is on the powerup itself:
void OnTriggerEnter2D(Collider2D collider2D)
{
if (collider2D.gameObject.tag == "Player")
{
Destroy(gameObject);
}
}
For some reason, any prefabs that I drop directly into my scene work perfectly, however instantiated ones get destroyed, but for some reason, do not trigger the "PoweredUp" boolean.
Here is a more complicated script that I have on the spawner objects:
public GameObject powerup;
public float minWait;
public float maxWait;
private bool isSpawning;
IEnumerator SpawnObject(float seconds)
{
Debug.Log("Waiting for " + seconds + " seconds");
yield return new WaitForSeconds(seconds);
Instantiate(powerup, transform.position, transform.rotation);
isSpawning = false;
}
void Update()
{
if (!isSpawning)
{
isSpawning = true;
StartCoroutine(SpawnObject(UnityEngine.Random.Range(minWait, maxWait)));
}
Any solutions, or ways I could have done this more efficiently?
UPDATE: I found out that the script on the Player object is running fine, but the boolean still isn't changing.
Ok I got it, there was a compiler warning referencing the line "PowerupTimer = PowerupTimer" so I just changed it to "PowerupTimer = 7f" which is pretty much the same thing.
I am very new to Unity and Vuforia and I have a study assignment to solve. I want to create 4 objects(Vuforia) in a scene that when they collide the four objects disappear and one fifth object appears augmented in the middle and when they disperse the 4 objects reappear. Any help would be very much appreciated. Please note that I don't know how to code in Unity. Please explain step by step to achieve the desired result. Thanks loads in advance.
I got some help setting the scene but the objects are not augmenting properly, they look like they drift away from the markers.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ProtoTypeV : MonoBehaviour
{
public GameObject objectOne, objectTwo, objectThree, mainObject;
public bool oneCollision, twoCollision, threeCollision;
public void FixedUpdate()
{
if (oneCollision && twoCollision && threeCollision)
{
this.gameObject.GetComponent<MeshRenderer>().enabled = false;
objectOne.GetComponent<MeshRenderer>().enabled = false;
objectTwo.GetComponent<MeshRenderer>().enabled = false;
objectThree.GetComponent<MeshRenderer>().enabled = false;
mainObject.SetActive(true);
}
else
{
Debug.Log("tracking");
this.gameObject.GetComponent<MeshRenderer>().enabled = true;
objectOne.GetComponent<MeshRenderer>().enabled = true;
objectTwo.GetComponent<MeshRenderer>().enabled = true;
objectThree.GetComponent<MeshRenderer>().enabled = true;
mainObject.SetActive(false);
}
}
public void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "ObjectOne")
{
oneCollision = true;
}
if(collision.gameObject.tag == "ObjectTwo")
{
twoCollision = true;
}
if (collision.gameObject.tag == "ObjectThree")
{
threeCollision = true;
}
}
public void OnCollisionExit(Collision collision)
{
if (collision.gameObject.tag == "ObjectOne")
{
oneCollision = false;
}
if(collision.gameObject.tag == "ObjectTwo")
{
twoCollision = false;
}
if(collision.gameObject.tag == "ObjectThree")
{
threeCollision = false;
}
}
}
I have some problems with a script for a "Field Of View" of the enemy. After watching a tutorial to create a field of view for the player I thought I can switch it to the enemy's so that they detect the player and do some other stuff. I created a boolean variable playerInRange to detect if the enemies can detect the player and set this variable to true or false.
It works fine with just one enemy. When I add another one, the new enemy will not detect the player. So maybe it is related to the coroutine, but I am not sure.
Here is a little bit of my code:
void Start() {
StartCoroutine("FindTargetsWithDelay", .2 f);
}
IEnumerator FindTargetsWithDelay(float delay) {
while (true) {
yield
return new WaitForSeconds(delay);
FindVisibleTargets();
}
}
public void FindVisibleTargets() {
visibleTargets.Clear();
Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, viewRadius, targetMask);
for (int i = 0; i < targetsInViewRadius.Length; i++) {
Transform target = targetsInViewRadius[i].transform;
Vector3 dirToTarget = (target.position - transform.position).normalized;
if (Vector3.Angle(transform.forward, dirToTarget) < viewAngle / 2) {
float dstToTarget = Vector3.Distance(transform.position, target.position);
if (!Physics.Raycast(transform.position, dirToTarget, dstToTarget, obstacleMask)) {
// Not so nice solution!
// The movement should be in a separate script!
visibleTargets.Add(target);
nav.SetDestination(player.position);
anim.SetBool("IsRunning", true);
if (dstToTarget < attackRange) {
playerInRange = true;
Debug.Log(playerInRange);
}
}
} else {
anim.SetBool("IsRunning", false);
playerInRange = false;
Debug.Log(playerInRange);
}
}
}
Thank you guys for your little hint. It was really a little hierarchy problem :( Sorry for that newbie/DAU question.
Cheers
Nico
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.