Hello Guest

Author Topic: tk2dTileMap tiles collision with tk2dSprite?  (Read 13181 times)

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
tk2dTileMap tiles collision with tk2dSprite?
« on: September 19, 2013, 07:06:15 pm »
I've done most of my collisions based on attaching a collider and then calling,

if(gameObject.collider.bounds.Intersects(otherObject.collider.bounds))
{
        //Do Something
}

but I cant seem to figure out how to call for the collision detection of a sprite and a tile maps individual sprites that make up the tile map.

What should i be referencing before getting to the .collider.bounds in my code, because I feel Itellisense searching is getting me no where.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #1 on: September 20, 2013, 12:08:50 am »
If you're doing collisions using bounds.intersects, then you could probably get away with simply checking renderer bounds. I.e. gameObject.renderer.bounds.Intersects(...).

You can't do that with tilemaps - the tilemaps get merged down into one big mesh for performance. You should probably look into Unity triggers to work out if you're colliding, or alternatively you can use ray casts too. And if you only care about whether the tiles are solid or not, then you could find the position in the tilemap using tilemap.GetTileAtPosition, and then work out if that tile is solid or not.

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #2 on: September 20, 2013, 01:10:05 am »
I was actually using the GetTileAtPosition before this, but I did actually find another way to do it by giving one of the tiles a prefab of itself with the collider that I needed to reference for my collisions.  This solution works for me so I though I would post my results of research so that others could benefit. I'm not sure if this will cause any future problems so if you know of anything that might occur that would be helpful.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #3 on: September 20, 2013, 10:00:50 am »
If you only need to detect with SOME tiles, then you could certainly use the prefab solution, but if you were intending to create loads of these prefabs (1000s) then perf will drop, but then at that point you'd be better off using triggers instead of manually checking for overlap.

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #4 on: September 20, 2013, 04:16:59 pm »
I see you point about using too many prefabs.  Although regarding your previous:
If you're doing collisions using bounds.intersects, then you could probably get away with simply checking renderer bounds. I.e. gameObject.renderer.bounds.Intersects(...).
I tried calling from gameobject.renderer.bounds but every time it said that there is no renderer attached to the TileMap.  Not sure why.

Also I tried your onTriggerEnter/onTriggerStay/onTriggerExit but it doesn't seem to be working for me.  Or at least it is not running the same amount of time as the update. With the function:

//variablespublic bool blockedLeft = false;
public Vector3 leftSideOfPlayerCollider;
//function
void OnCollisionEnter(Collision other)
{
      if(other.collider.bounds.Contains(leftSideOfPlayerCollider)
      {
            blockedLeft  = true;
      }
}

But Contains seem to look at everything inside my tile map because I'm using a test tile map that 13 by 10.  I also have a tile that goes around the outline of the tilemap which has a box collider on the sprite.  So Contains looks at everything instead of just the stuff that’s inside the mesh collider of the tile map render data chunk.

I would use Intersects but then it wouldn’t tell me what side of the player is intersecting on.  (I was an XNA user up until Microsoft decided to pretty much kill it and did much of my boxed collisions using Rect.Left/Right/etc..)

Is there a more effective way to go about this or am I running around in circles trying to use the bounds?
If so what should I be using instead because I would like to use the actual collider but it seems my only success so far was with looking at the tile in the next position that I am traveling towards.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #5 on: September 20, 2013, 05:36:31 pm »
What exactly are you trying to do here? Do you just need to know when you've hit a tile, or do you need to know when you've hit a particular tile. How are you moving your character, etc. Also, if you can say what kind of game you're making that'll help too. There might be an easier solution to this, but depends very much on what you're trying to do

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #6 on: September 20, 2013, 05:55:42 pm »
I have a sprite that moves in all directions but looks like a top down game.  Kind of like the pokemon ranger games.  (Actually using their sprites for testing).  And I need to know is when the animated sprite collides with a tile with a box collider and stop them from going past it.  Right now for testing purposes I have a square tile map with the outlining tiles being tiles with a box collider on them.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #7 on: September 20, 2013, 09:12:29 pm »
I suggest looking into this example. It doesn't use tilemaps, but the same principle will apply directly.
http://unikronsoftware.com/2dtoolkit/forum/index.php/topic,2476.0.msg12395.html#msg12395

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #8 on: September 24, 2013, 11:09:15 pm »
Not sure what I should be grasping from the links information because the downloadable file doesn't seem to load in unity.  This is my code right now and it some what accomplishes what I wanted to do but I would like to use the collisders in a way that if another collider has a point that is the same with the players collider, then figure out how to stop the player from moving in that direction.  With my code I still get some instances where the player is somewhat in an area he shouldn't be but other then that it works fine.  Any improvements on this code is also appreciated.

Code: [Select]
using UnityEngine;
using System.Collections;

public class PlayerScriptV2 : MonoBehaviour {

#region variables
public tk2dSpriteAnimator currentAnimation;
public tk2dTileMap tileMapFinder;

#region movement variables
public bool wasWDown = false;
public bool wasADown = false;
public bool wasSDown = false;
public bool wasDDown = false;
public bool isRunning = false;
public float iSpeed = 1.0f;
public bool blockedL = false;
public bool blockedR = false;
public bool blockedU = false;
public bool blockedD = false;
public int currentTileId;
public int currentTileX;
public int currentTileY;
public int leftMiddleTileId;
public int leftTopTileId;
public int leftBottomTileId;
public int rightMiddleTileId;
public int rightTopTileId;
public int rightBottomTileId;
public int upMiddleTileId;
public int upLeftTileId;
public int upRightTileId;
public int downMiddleTileId;
public int downLeftTileId;
public int downRightTileId;
#endregion
#endregion

// Use this for initialization
void Start () {
currentAnimation = GetComponent<tk2dSpriteAnimator>();
tileMapFinder = tk2dTileMap.FindObjectOfType(typeof(tk2dTileMap)) as tk2dTileMap;
}

// Update is called once per frame
void Update () {

tileMapFinder = tk2dTileMap.FindObjectOfType(typeof(tk2dTileMap)) as tk2dTileMap;

#region motion control
#region load needed variables
currentTileId = tileMapFinder.GetTileIdAtPosition(gameObject.collider.bounds.center, 0);
tileMapFinder.GetTileAtPosition(gameObject.collider.bounds.center, out currentTileX, out currentTileY);

//collider draws from bottom-left to top-right
leftTopTileId = tileMapFinder.GetTileIdAtPosition(gameObject.collider.bounds.min, 0);
leftMiddleTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.min.x,gameObject.collider.bounds.center.y, gameObject.collider.bounds.center.z) , 0);
leftBottomTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.min.x,gameObject.collider.bounds.max.y, gameObject.collider.bounds.center.z) , 0);

rightTopTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.max.x, gameObject.collider.bounds.min.y, gameObject.collider.bounds.max.z), 0);
rightMiddleTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.max.x,gameObject.collider.bounds.center.y, gameObject.collider.bounds.center.z) , 0);
rightBottomTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.max.x,gameObject.collider.bounds.max.y, gameObject.collider.bounds.center.z) , 0);

upLeftTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.min.x, gameObject.collider.bounds.max.y, gameObject.collider.bounds.center.z), 0);
upMiddleTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.center.x,gameObject.collider.bounds.max.y, gameObject.collider.bounds.center.z) , 0);
upRightTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.max.x, gameObject.collider.bounds.max.y, gameObject.collider.bounds.center.z), 0);

downLeftTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.min.x, gameObject.collider.bounds.min.y, gameObject.collider.bounds.center.z), 0);
downMiddleTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.center.x,gameObject.collider.bounds.min.y, gameObject.collider.bounds.center.z) , 0);
downRightTileId = tileMapFinder.GetTileIdAtPosition(new Vector3(gameObject.collider.bounds.max.x, gameObject.collider.bounds.min.y, gameObject.collider.bounds.center.z), 0);
#endregion

#region if wall is blocked test
//leftBlock test
if((leftMiddleTileId == 12 && leftTopTileId == 12 && leftBottomTileId == 12) || (leftMiddleTileId == 12 && leftTopTileId != 12 && leftBottomTileId == 12) || (leftMiddleTileId == 12 && leftTopTileId == 12 && leftBottomTileId != 12))
{
blockedL = true;
}
else
{
blockedL = false;
}
//rightBlock test
if((rightMiddleTileId == 12 && rightTopTileId == 12 && rightBottomTileId == 12) || (rightMiddleTileId == 12 && rightTopTileId != 12 && rightBottomTileId == 12) || (rightMiddleTileId == 12 && rightTopTileId == 12 && rightBottomTileId != 12))
{
blockedR = true;
}
else
{
blockedR = false;
}
//upBlock test
if((upMiddleTileId == 12 && upLeftTileId == 12 && upRightTileId == 12) || (upMiddleTileId == 12 && upLeftTileId != 12 && upRightTileId == 12) || (upMiddleTileId == 12 && upLeftTileId == 12 && upRightTileId != 12))
{
blockedU = true;
}
else
{
blockedU = false;
}
//downBlock test
if((downMiddleTileId == 12 && downLeftTileId == 12 && downRightTileId == 12) || (downMiddleTileId == 12 && downLeftTileId != 12 && downRightTileId == 12) || (downMiddleTileId == 12 && downLeftTileId == 12 && downRightTileId != 12))
{
blockedD = true;
}
else
{
blockedD = false;
}
#endregion

#region input capture
if(Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.S))
{
currentAnimation.Play("Run_Up");
if(!blockedU)
{
transform.Translate(0,((iSpeed * Time.deltaTime)+0.1f),0);
}
wasWDown = true;
wasADown = false;
wasSDown = false;
wasDDown = false;
isRunning = true;
}
if(Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.D))
{
currentAnimation.Play("Run_Left");
currentAnimation.SetFrame(0);
if(!blockedL)
{
transform.Translate(-((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = false;
wasADown = true;
wasSDown = false;
wasDDown = false;
isRunning = true;
}
if(Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.W))
{
currentAnimation.Play("Run_Down");
if(!blockedD)
{
transform.Translate(0,-((iSpeed * Time.deltaTime) + 0.1f),0);
}
wasWDown = false;
wasADown = false;
wasSDown = true;
wasDDown = false;
isRunning = true;
}
if(Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.A))
{
currentAnimation.Play("Run_Right");
if(!blockedR)
{
transform.Translate(((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = false;
wasADown = false;
wasSDown = false;
wasDDown = true;
isRunning = true;
}
if(Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.D))
{
currentAnimation.Play("Run_LeftDown");
if(!blockedD)
{
transform.Translate(0,-((iSpeed * Time.deltaTime) + 0.1f),0);
}
if(!blockedL)
{
transform.Translate(-((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = false;
wasADown = true;
wasSDown = true;
wasDDown = false;
isRunning = true;
}
if(Input.GetKey(KeyCode.D) && Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.A))
{
currentAnimation.Play("Run_RightDown");
if(!blockedD)
{
transform.Translate(0,-((iSpeed * Time.deltaTime) + 0.1f),0);
}
if(!blockedR)
{
transform.Translate(((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = false;
wasADown = false;
wasSDown = true;
wasDDown = true;
isRunning = true;
}
if(Input.GetKey(KeyCode.A) && Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.D))
{
currentAnimation.Play("Run_LeftUp");
if(!blockedU)
{
transform.Translate(0,((iSpeed * Time.deltaTime) + 0.1f),0);
}
if(!blockedL)
{
transform.Translate(-((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = true;
wasADown = true;
wasSDown = false;
wasDDown = false;
isRunning = true;
}
if(Input.GetKey(KeyCode.D) && Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S) && !Input.GetKey(KeyCode.A))
{
currentAnimation.Play("Run_RightUp");
if(!blockedU)
{
transform.Translate(0,((iSpeed * Time.deltaTime) + 0.1f),0);
}
if(!blockedR)
{
transform.Translate(((iSpeed * Time.deltaTime) + 0.1f),0,0);
}
wasWDown = true;
wasADown = false;
wasSDown = false;
wasDDown = true;
isRunning = true;
}

if(isRunning)
{
if(!Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.W) && !Input.GetKey(KeyCode.S))
{
isRunning = false;
}
}
else
{
if(wasWDown && !wasADown && !wasDDown && !wasSDown)
{
currentAnimation.Play("Idle_Up");
currentAnimation.SetFrame(0);
}
if(wasADown && !wasWDown && !wasSDown && !wasDDown)
{
currentAnimation.Play("Idle_Left");
currentAnimation.SetFrame(0);
}
if(wasDDown && !wasWDown && !wasSDown && !wasADown)
{
currentAnimation.Play("Idle_Right");
currentAnimation.SetFrame(0);
}
if(wasWDown && wasADown && !wasDDown && !wasSDown)
{
currentAnimation.Play("Idle_LeftUp");
currentAnimation.SetFrame(0);
}
if(wasWDown && !wasADown && wasDDown && !wasSDown)
{
currentAnimation.Play("Idle_RightUp");
currentAnimation.SetFrame(0);
}
if(wasSDown && !wasADown && !wasDDown && !wasWDown)
{
currentAnimation.Play("Idle_Down");
currentAnimation.SetFrame(0);
}
if(wasSDown && wasADown && !wasDDown && !wasWDown)
{
currentAnimation.Play("Idle_LeftDown");
currentAnimation.SetFrame(0);
}
if(wasSDown && !wasADown && wasDDown && !wasWDown)
{
currentAnimation.Play("Idle_RightDown");
currentAnimation.SetFrame(0);
}
}
#endregion
#endregion
}
}

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #9 on: September 25, 2013, 10:41:27 am »
What error do you get with the file? That sample shows how you can do that with the character controller - you don't need to mess about with your own collision detection if you use that. The code is significantly simpler as well. If you still can't get it to load, email support and I'll send it via email.

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #10 on: October 05, 2013, 03:26:02 am »
I've looked into character controller but it seems to use capsule collision instead of box collision.  Is their a way to change it because it seems from what I've seen it needs to be capsule collision.

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #11 on: October 05, 2013, 03:57:42 am »
I've looked into character controller but it seems to use capsule collision instead of box collision.  Is their a way to change it because it seems from what I've seen it needs to be capsule collision.
Here's some pics to better see what I'm working with.  To explain again I'm looking for a way to only keep it on the tiles that are imaged and what I have been doing so far is stopping it from going onto the black tiles that surround the imaged tiles.

Here's the players box collider pic:
http://img31.imageshack.us/img31/9646/dl.png

And here's the tilemap collider pic:
http://img69.imageshack.us/img69/370/t8ch.png

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #12 on: October 05, 2013, 12:41:30 pm »
Yeah the char controller is a capsule. That probably isn't suitable in this case, but you could try using raycasts to work out where to stop. Doing it expliclty like you are is possible, but you will need to work out all the corner cases.

IMO, its often easier if you can rely on the collision system to do the nasty work for you. You can also try rigidbody.SweepTest to find out where your collider would have first hit the environment and make a decision from there.

nicktp491

  • 2D Toolkit
  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #13 on: October 05, 2013, 08:09:18 pm »
I tried RayCasting and I was able to get closer to what I was trying to do but unfortunately I still came up with the same problem, which was the corners.  I've been messing around with tutorials and now I have a new problem.  I have the collider of the player not set to is trigger and the player can't leave the area now, but two things occur.  The first is that it looks like the player is fidgeting when colliding with the wall.  And the other is that after I let go of the key command to move him, he starts drifting in the opposite direction.

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: tk2dTileMap tiles collision with tk2dSprite?
« Reply #14 on: October 05, 2013, 10:09:58 pm »
Its quite impossible to guess whats gone wrong from your description - there are so many variables at play here. If its drifting, then perhaps you have a rigidbody there that shouldn't be there?