Collider triggers firing on launch - unity3d

I have a "zone", with four borders; north, east, south and west. On these borders, I have 2d colliders, like this :
So, on a zone, I would have four instances of this, for each border. In the script for GridBorderController, I have this :
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == Const.TAG_PLAYER)
{
print("enter " + gridBorderSide.ToString());
/*var pos = new Vector3(20, 20, 0);
var zoneInstance = Instantiate(this, pos, Quaternion.identity, this.transform);
var tileMaker = zoneInstance.transform.GetChild(0);
var terrainDrawer = tileMaker.GetComponent<TerrainDrawer>();
print(terrainDrawer.sprites.Length);*/
}
}
When I launch the game, I create an instance of this zone, and this is what I get in my console :
This is how I start the controller :
void Start()
{
boxCollider2D = GetComponent<BoxCollider2D>();
terrainDrawer = GetComponentInParent<TerrainDrawer>();
collider = GetComponent<Collider2D>();
collider.enabled = false;
var gridRadius = terrainDrawer.gridRadius;
float borderOffset = borderWidth / 2;
switch (gridBorderSide)
{
case GridBorderSide.North:
case GridBorderSide.South:
{
boxCollider2D.size = new Vector2(gridRadius/2 , borderWidth);
if(gridBorderSide == GridBorderSide.North)
{
boxCollider2D.transform.position += new Vector3(0, (gridRadius / 4) - (borderOffset));
}
else
{
boxCollider2D.transform.position -= new Vector3(0, (gridRadius / 4) - (borderOffset));
}
break;
}
case GridBorderSide.East:
case GridBorderSide.West:
{
boxCollider2D.size = new Vector2(borderWidth, gridRadius / 2);
if (gridBorderSide == GridBorderSide.East)
{
boxCollider2D.transform.position += new Vector3((gridRadius / 4) - (borderOffset), 0 );
}
else
{
boxCollider2D.transform.position -= new Vector3((gridRadius / 4) - (borderOffset), 0);
}
break;
}
}
collider.enabled = true;
}
When I walk over the collider with my player, it does fire as well, so I know that part works, but can anyone explain the me why the triggers fire immediately on launch?

Related

Move Object around a platform of tiles in Unity

I want to make a spinning spike to move around a platform made out of tiles like in the following
I have written every possible state on where to move when platform tiles block the spike's way. It would look something like this
for (int i = 0; i < platformTileMap.Length; i++)
{
if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(0, -1, 0))) // BOTTOM
{
moveX = moveDir;
}
else if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(0, 1, 0))) // TOP
{
moveX = -moveDir;
}
else if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(-1, -1, 0))) //BOT LEFT
{
if (moveDir == 1)
{
moveY = -1;
}
else moveX = moveDir;
}
else if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(1, 1, 0))) //TOP RIGHT
{
if (moveDir == 1)
{
moveY = 1;
}
else moveX = -moveDir;
}
else if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(1, -1, 0))) // BOT RIGHT
{
if (moveDir == 1)
{
moveX = moveDir;
}
else
{
moveY = -1;
}
}
else if (platformTileMap[i].HasTile(cellPosition + new Vector3Int(-1, 1, 0))) // TOP LEFT
{
if (moveDir == -1)
{
moveY = 1;
}
else
{
moveX = -moveDir;
}
}
I feel like there has to be a more efficient way to solve this. Do I really have to write every possibility in if statements? Can I achieve this with pathfinding?
How about this
Use raycast
Place Empty GameObject and rotate spike when it arrives them
You could create an array of points to move to.
public Vector3[] movePoints;
You can set movePoints in inspector or in code (such as Start function) user choice
In the update loop lerp to the next point in sequence, when arrived pull the next point, unless we are at the end of the array then pull the first point in the array, rinse and repeat forever.
https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
Set this up properly once, when you make more blades and different configurations or want to change speed it will be ez pz.
For anyone interested. Here is how i solved it:
GridLayout platformGridLayout;
Grid platformGrid;
Tilemap[] platformTileMap;
[SerializeField] float rotationSpeed;
[SerializeField] float moveSpeed;
[SerializeField] private LayerMask platformLayerMask;
Vector3Int startPos;
Vector3Int currentCellPosition;
Vector3 raycastPlatformDir;
Vector3 raycastMoveDir;
float platformRaycastDist;
// Start is called before the first frame update
void Start()
{
movePoints = new List<Vector3Int>();
platformGridLayout = transform.parent.GetComponentInParent<GridLayout>();
platformGrid = transform.parent.GetComponentInParent<Grid>();
startPos = platformGridLayout.WorldToCell(transform.position);
Debug.Log("Cell Startposition: " + startPos);
PlatformToMoveOn();
GetStartRaycastDir();
platformRaycastDist = platformGridLayout.cellSize.x;
Debug.Log("CellCenterToWorld of Startposition: " + platformGrid.GetCellCenterWorld(startPos));
Debug.Log(platformGrid.GetCellCenterLocal(currentCellPosition + Vector3Int.FloorToInt(raycastPlatformDir) + Vector3Int.FloorToInt(raycastMoveDir)));
}
private void PlatformToMoveOn()
{
platformTileMap = new Tilemap[2];
platformTileMap[0] = GameObject.Find("Platform").GetComponent<Tilemap>();
platformTileMap[1] = GameObject.Find("MovingPlatform").GetComponent<Tilemap>();
}
private void GetStartRaycastDir()
{
for (int i = 0; i < platformTileMap.Length; i++)
{
if (platformTileMap[i].HasTile(startPos + new Vector3Int(0, -1, 0))) // BOTTOM
{
raycastPlatformDir = Vector3.down;
}
else if (platformTileMap[i].HasTile(startPos + new Vector3Int(0, 1, 0))) // TOP
{
raycastPlatformDir = Vector3.up;
}
else if (platformTileMap[i].HasTile(startPos + new Vector3Int(1, 0, 0))) // RIGHT
{
raycastPlatformDir = Vector3.right;
}
else if (platformTileMap[i].HasTile(startPos + new Vector3Int(-1, 0, 0))) // LEFT
{
raycastPlatformDir = Vector3.left;
}
}
raycastMoveDir = Quaternion.Euler(0, 0, 90) * raycastPlatformDir * Mathf.Sign(moveSpeed);
//raycastMoveDir = new Vector3(raycastPlatformDir.y, raycastPlatformDir.x) * Mathf.Sign(moveSpeed);
}
// Update is called once per frame
void Update()
{
MoveSpike();
}
private void MoveSpike()
{
currentCellPosition = platformGridLayout.WorldToCell(transform.position); // + raycastPlatformDir * platformGridLayout.cellSize.y / 2;
// Debug.Log(cellPosition);
//Debug.Log(raycastMoveDir);
transform.Rotate(0, 0, 300 * rotationSpeed * Time.deltaTime);
RaycastHit2D raycastMove = Physics2D.Raycast(platformGrid.GetCellCenterLocal(currentCellPosition),raycastMoveDir,0.01f,platformLayerMask);
RaycastHit2D raycastPlatform = Physics2D.Raycast(platformGrid.GetCellCenterLocal(currentCellPosition), raycastPlatformDir, platformRaycastDist, platformLayerMask);
Debug.DrawRay(transform.position, raycastMoveDir * 0.01f, Color.red);
Debug.DrawRay(transform.position, raycastPlatformDir * platformRaycastDist, Color.green);
if (currentCellPosition != startPos) { // Check on Platform corners
Debug.Log("Checking");
if (raycastMove.collider != null)
{
// reassign raycastsdirections
RotateRaycastDirections(1);
Debug.Log("Spike Collision");
}
else if (raycastPlatform.collider == null)
{
RotateRaycastDirections(-1);
Debug.Log("Spike on Platform");
}
startPos = currentCellPosition;
}
/*transform.position = Vector3.MoveTowards(transform.position,
platformGrid.GetCellCenterLocal(currentCellPosition + Vector3Int.FloorToInt(raycastPlatformDir) + Vector3Int.FloorToInt(raycastMoveDir)), moveSpeed * Time.deltaTime); */
transform.Translate(raycastMoveDir.x * Mathf.Abs(moveSpeed) * Time.deltaTime, raycastMoveDir.y * Mathf.Abs(moveSpeed) * Time.deltaTime, 0, Space.World);
}
private void RotateRaycastDirections(int angle)
{
raycastPlatformDir = Quaternion.Euler(0, 0, 90) * raycastPlatformDir * angle * Mathf.Sign(moveSpeed);
raycastMoveDir = Quaternion.Euler(0, 0, 90) * raycastMoveDir * angle * Mathf.Sign(moveSpeed);
// raycastPlatformDir = new Vector3(raycastPlatformDir.y, raycastPlatformDir.x) * angle;
//raycastMoveDir = new Vector3(raycastMoveDir.y, raycastMoveDir.x) * -angle;
}
Edit:
This doesnt work on moving Platforms though. Any ideas how i could fix that? I tried changing the raycast position to the tilemapscentercell position but it doesnt work.

Unity 2D Platformer - making my enemy not see through walls

basicly i'm searching for an idea. How to make my Enemy patroling, but when it reaches the Player - it rush and deal damage, but in the same time when it reach the wall and player is standing behind the wall it Don't attack. You know - i don't want to let them see through walls.
I have made simple Game Object (rectangle) to point it's sight, it is working correctly but i want to improve some of it.
To make it quckier... i just want to make my enemies attack me but to not seen me througth walls
Some code:
[DamageFromEnemy.cs]
private void FixedUpdate()
{
isThatPlayer = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, PlayerLayer);
isThatWall = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, gameObject.GetComponent<EnemyScript>().WallLayer);
if (isThatWall == true && gameObject.GetComponent<EnemyScript>().movingRight == true)
{
PlayerDetector.transform.Translate(new Vector3(changePosX, 0, 0));
//playerDetectX -= PlayerDetector.transform.position.x; // Lowering size. Not Working
changePosX = (playerDetectX / 2) * (1 / enemyScaleX) + (enemyScaleX / 2) * (1 / enemyScaleX);
Debug.Log("pozycja x: " + changePosX);
}
if (isThatWall == true && gameObject.GetComponent<EnemyScript>().movingRight == false)
{
PlayerDetector.transform.Translate(new Vector3(- changePosX, 0, 0));
//playerDetectX -= PlayerDetector.transform.position.x; // Lowering size. Not Working
changePosX = (playerDetectX / 2) * (1 / enemyScaleX) + (enemyScaleX / 2) * (1 / enemyScaleX);
Debug.Log("pozycja x: " + changePosX);
}
DetectPlayer();
AttackTimer();
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(PlayerDetector.position, new Vector3(playerDetectX, playerDetectY));
}
[EnemyScript.cs]
void Update ()
{
trap = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, TrapLayer);
otherEnemy = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, EnemyLayer);
if (health <= 0)
{
Destroy(gameObject);
}
transform.Translate(Vector2.right * speed * Time.deltaTime );
RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);
RaycastHit2D wallInfoR = Physics2D.Raycast(wallDetection.position, Vector2.right, distance, WallLayer);
RaycastHit2D wallInfoL = Physics2D.Raycast(wallDetection.position, Vector2.left, -distance, WallLayer);
if (groundInfo.collider == false || trap == true || otherEnemy == true || wallInfoR == true || wallInfoL == true)
{
if(movingRight == true)
{
transform.eulerAngles = new Vector3(0, -180, 0);
movingRight = false;
}
else
{
transform.eulerAngles = new Vector3(0, 0, 0);
movingRight = true;
}
}
}
Some Gif Feedback
At last gifs frames you can see that it bugs sometimes.
public PlayerControls player;
public LayerMask WallLayer;
player = FindObjectOfType<PlayerControls>();
RaycastHit2D checkWallsToHero = Physics2D.Raycast(wallToHeroRay.position, player.transform.position, 150,WallLayer);
if (checkWallsToHero == true)
{
playerCheck = false;
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(PlayerDetector.position, new Vector3(playerDetectX, playerDetectY));
Gizmos.DrawLine(wallToHeroRay.position, player.transform.position);
}
[New Code sample - propably wrong]:
isThatPlayer = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, PlayerLayer);
isThatWall = Physics2D.OverlapBox(PlayerDetector.position, new Vector2(playerDetectX, playerDetectY), 0, gameObject.GetComponent<EnemyScript>().WallLayer);
RaycastHit2D checkWallsToHero = Physics2D.Raycast(wallToHeroRay.position, player.transform.position, 0, gameObject.GetComponent<EnemyScript>().WallLayer);
if (checkWallsToHero.collider != true /*&& isThatPlayer == true*/)
{
Debug.Log("Pierwszy state");
Debug.Log(checkWallsToHero.collider);
//Debug.Log(isThatPlayer);
//Debug.Log("Hit: " + checkWallsToHero.collider.gameObject.name);
playerCheck = false;
enemyAttackReady = false;
coolDownTimer = 0;
enemyAttackCD = 0;
}
else if (checkWallsToHero.collider == true && isThatPlayer == true)
{
Debug.Log(checkWallsToHero.collider);
Debug.Log("Drugi state");
ReadyToAttack(); //charging enemy
DetectPlayer(); //bool to true when OverlapBox hits player
AttackTimer(); //cd between enemy attacks
}
if (Physics2D.Raycast2D
(wallToHeroRay.position,player.transform.position,out hit,10)
&&hit.transform.gameObject.tag == "Player")
{
RayHit = true;
}
else {
RayHit = false;
}
to use this you will have to tag your player as 'Player' then your ray will only give you a hit if it hits the player itself, and not a wall
Edit: this is code i threw together following #Draco18s's idea in the comments, if it works for you, tell him thank you. i just thought it made enough sense he should have put it as an answer

Unity- Moving an Object to the left on a Scrolling Background

I am trying to create a simple Infinite Runner game on Unity and ran into a problem. The task is to make a ball spawn on the floor and immediately begin to roll to the left towards the Player. I have tried a number of ways to implement it, but it does not seem to work. Here is my most recent attempt:
public class ObstaclePool : MonoBehaviour {
public GameObject columnPrefab;
public GameObject ballPrefab;
public int obstaclePoolSize = 5;
public float spawnRate = 3f;
private GameObject[] obstacles;
private int currentObstacle = 0;
private Vector2 objectPoolPosition = new Vector2(-15, -25);
private float timeSinceLastSpawned;
private float spawnXPosition;
private bool hasCalled = false;
private int dice;
bool beforeBall = false;
// Use this for initialization
void Start () {
timeSinceLastSpawned = 0f;
SetupObstacles();
}
private void SetupObstacles()
{
obstacles = new GameObject[obstaclePoolSize];
for (int i = 0; i < obstaclePoolSize; i++)
{
dice = Random.Range(1, 3);
if (dice == 1)
{
obstacles[i] = (GameObject)Instantiate(columnPrefab, objectPoolPosition, Quaternion.identity);
}
else if (dice == 2)
{
obstacles[i] = (GameObject)Instantiate(ballPrefab, objectPoolPosition, Quaternion.identity);
}
}
}
// Update is called once per frame
void Update () {
timeSinceLastSpawned += Time.deltaTime;
if (GameControl.instance.gameOver == false && timeSinceLastSpawned >= spawnRate)
{
timeSinceLastSpawned = 0f;
if (hasCalled == false)
{
spawnXPosition = 10f;
hasCalled = true;
}
else
{
spawnXPosition = Random.Range(6f, 10f);
}
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
else {
if (beforeBall == true)
{
spawnXPosition = Random.Range(9f, 10f);
beforeBall = false;
}
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -7.08f);
Debug.Log(spawnXPosition);
}
currentObstacle++;
if (currentObstacle >= obstaclePoolSize)
{
currentObstacle = 0;
SetupObstacles();
hasCalled = false;
}
}
}
}
For a quick explanation of my code: I have an array of size 5. It holds the obstacles that I have created. When deciding what to put inside the array, I generated a random number (1 or 2). If it's a 1, I put in a column. If it's a 2, I put in a ball. These obstacles are spawned off-screen. Then, I move them in the actual scene after using random number to determine the X position.
This part in particular is where I try to implement it:
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
I may have some remnants of stuff that I have been testing out, so some of the code may seem redundant and messy.
I also tried using Translate and Velocity with no success. I also have a ScrollingObject code and a RepeatingBackground code. I placed the ScrollingObject code in the Ball prefab too. (Also, tried taking it out -> ball rolls to the right). These codes come from the Unity tutorial.
RepeatingBackground:
public class RepeatingBackground : MonoBehaviour {
private BoxCollider2D groundCollider;
private float groundHorizontalLength;
// Use this for initialization
private void Awake () {
groundCollider = GetComponent<BoxCollider2D>();
groundHorizontalLength = groundCollider.size.x;
}
// Update is called once per frame
private void Update () {
if (transform.position.x < -groundHorizontalLength)
{
RepositionBackground();
}
}
private void RepositionBackground()
{
Vector2 groundOffSet = new Vector2(groundHorizontalLength * 2f, 0);
transform.position = (Vector2)transform.position + groundOffSet;
}
}
ScrollingObjects:
public class ScrollingObject : MonoBehaviour {
private Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D>();
rb2d.velocity = new Vector2(GameControl.instance.scrollSpeed, 0);
}
// Update is called once per frame
void Update () {
if (GameControl.instance.gameOver == true)
{
rb2d.velocity = Vector2.zero;
}
}
}
It looks like you simply named the wrong object in your first example.
if (obstacles[currentObstacle].transform.tag == "Ball")
{
spawnXPosition = Random.Range(9f, 10f);
obstacles[currentObstacle].transform.position = new Vector2(spawnXPosition, -1.84f);
ballPrefab.GetComponent<Rigidbody2D>().AddForce(new Vector2(-100f, 0) * 5);
beforeBall = true;
}
Notice how here you added the force to the prefab, not an instantiated version of the prefab.
I played around a bit more and got it to work. I just wrote another script that added force to the object. I still do not understand why my original way did not work though.

Unity 2D: Destroy all overlapping objects

I am making a 2D isometric citybuilding game. The world is devided into tiles and you can click a button to start the placement of a building. The building will follow your mouse across the map and when you click another button it will place (this works fine). But if you want to place a (new) building over another (old) building, that (old) building needs to be destroyed.
All buildings have a Ridgidbody2D (kinedynamic) and a Boxcollider2D.
Picture: The setup for the Building
Ps: this is my first question on this forum if I could improve my questions please tell me.
private bool Place;
public bool Destr;
Vector2 pz;
private SpriteRenderer spriteRenderer;
public void Awake()
{
Place = true;
}
public void Update()
{
if (Place)
{
pz = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (Mathf.RoundToInt(pz.x) % 2 != 0)
pz.x = Mathf.RoundToInt(pz.x) + 1;
if (Mathf.RoundToInt(pz.x) % 4 == 0)
{
pz.x = Mathf.RoundToInt(pz.x);
if (Mathf.RoundToInt(pz.y) % 2 == 0)
{
pz.y = Mathf.RoundToInt(pz.y) + 1;
}
else
pz.y = Mathf.RoundToInt(pz.y);
}
else
{
pz.x = Mathf.RoundToInt(pz.x);
if (Mathf.RoundToInt(pz.y) % 2 == 0)
{
pz.y = Mathf.RoundToInt(pz.y);
}
else
pz.y = Mathf.RoundToInt(pz.y) + 1;
}
transform.position = pz;
}
if (Input.GetButtonDown("Place2") && Place)
{
Place = false;
float IsoX = Mathf.Abs(pz.x) / 2;
float IsoY = (pz.y - 1 - IsoX) / 2;
spriteRenderer = GetComponent<SpriteRenderer>();
spriteRenderer.sortingOrder = -(20 * Mathf.RoundToInt(IsoY) + Mathf.RoundToInt(IsoX)) + 1;
// New code
for (var i = 0; i < Obj.Count; i++)
{
Destroy(Obj[i]);
}
}
}
void OnCollisionEnter2D(Collision2D other)
{
if(Place)
{
Obj.Add(other.gameObject);
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (Place)
{
Obj.Remove(other.gameObject);
}
}

Unity - Change cube color before placement

So, I am making a Minecraft-like game, and you basically move around on a pre-generated floor and place blocks. My problem is that I need to get the ability for the player to change the block color by hitting a numberpad key, ex: 1 for red, 2 for blue, and so on.
Here is the script that generates the floor, and handles block placement.
var range : float = Mathf.Infinity;
var hit : RaycastHit;
for (var y = -4; y < 50; ++y)
for (var x = -4; x < 50; ++x) {
var block : GameObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
block.transform.position = transform.position + Vector3(x, -3, y);
}
function Update () {
if (Input.GetMouseButtonDown(0) && Hit()) {
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = hit.transform.position + hit.normal;
}
if (Input.GetMouseButtonDown(1) && Hit())
Destroy(hit.transform.gameObject);
if (Input.GetKeyDown(KeyCode.Keypad1)) {
cube.renderer.material.color = Color.red;
}
if (Input.GetKeyDown(KeyCode.Keypad2)) {
cube.renderer.material.color = Color.blue;
}
if (Input.GetKeyDown(KeyCode.Keypad3)) {
cube.renderer.material.color = Color.yellow;
}
if (Input.GetKeyDown(KeyCode.Keypad4)) {
cube.renderer.material.color = Color.green;
}
if (Input.GetKeyDown(KeyCode.Keypad5)) {
cube.renderer.material.color = Color.magenta;
}
}
function Hit() : boolean {
return Physics.Raycast(transform.position, transform.forward, hit, range, 1);
}