Search Unity

Using effectors with tilemap and composite colliders (specifically buoyancy eff.)

Discussion in '2D' started by verity147, Nov 26, 2019.

  1. verity147

    verity147

    Joined:
    Jun 22, 2017
    Posts:
    7
    Hello there,

    I'm having a weird amount of trouble finding anything on how to use tilemaps with collider effectors.

    I have a 2D platformer built with tilemaps, one of which is meant for bodies of water. This tilemap has a tilemap collider, composite collider and buoyancy effector in which I adjusted the surface level when building the tilemap. Now I've noticed that this surface level is relative to the tilemap object itself (or so it seems), not as I thought, relative to the surface of the colliders. Which means I can only ever have it be fitting for bodies of water which have their upper border on the same y coordinate.

    This is an example, my colliders are pink (better contrast) and the surface level is the cyan line. It's all painted onto the same tilemap, see settings below.

    Am I meant to have one tilemap per body of water? What is the intended way to use these components together?
     

    Attached Files:

  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    The BuoyancyEffector2D works the same as all other effectors but its response is obviously unique. It is designed to be used by colliders marked as triggers so there's no collision response. All effectors look at contacts and produce a response (in this case buoyancy) accordingly. Now whether you define these collider regions using circles, capsule, boxes, tilemaps, composites (whatever) doesn't matter. How you define the collider geometry is completely under your control. Tilemaps were created a long time after these effectors but the above description is why they "work together", because they don't know about each other. It's a pure behaviour response based upon contacts between colliders.

    Regardless, the surface level property is as its descriptions in the docs state, it's a world-space offset along the world Y axis (can also be scaled) from the GameObject position. It isn't relative to colliders, tilemaps or whatever as again it knows nothing about their presence. So if you want to have two separate bodies of water, each with its own surface level then they need to be two separate effectors because an effector cannot have two surface levels. It cannot know multiple surface levels all defined in the same collider (in this case a CompositeCollider2D).

    In the end, the effector sees contacts and then calculates where the collider is with respect to the defined surface level. It then applies the appropriate forces at the correct positions to the Rigidbody2D.

    It's not clear on the context of this water within a tilemap but you can either use a separate tilemap for each body of water or it's far easier to just use a child GameObject with a trigger BoxCollider2D (or whatever) with a BuoyancyEffector2D. These things can overlap regions in the tilemap where you want water. Obviously this can create a design disconnect between the drawn water tiles and the GameObject defining the behaviour.

    Although it's a bit of a hack and you don't get rotational behaviour as you do with the surface level, it is possible to define multiple regions and have the surface level set to way above all of them. What happens then is that the effector will cause upwards buoyancy movement until it forces the body above the trigger collider and because it has no contact it stops moving it upwards so it'll sink back with gravity. This won't produce any rotational effects as you normally get at the surface however because the effector still thinks the collider is completely immersed so the force is applied to the center-of-mass. This though is just the contact appearing then disappearing causing the buoyancy to be turned on and off which isn't identical to the behaviour at the surface but it depends on what you want.

    Note that it's not too difficult to implement a simple buoyancy system if all you want to do is detect it's hit those triggers and apply an upwards buoyancy force. It's also possible to dynamically create these effectors in the editor based upon some simple flood-fill detection algorithm to define the water region.
     
    SpeddyFalcon and verity147 like this.
  3. verity147

    verity147

    Joined:
    Jun 22, 2017
    Posts:
    7
    Wow, that is one detailed explanation, thank you very much. I'm glad I didn't just miss something obvious. In my case I guess I'll remove the colliders from the tilemap and add individual box colliders for each body of water since there won't be that many in the game so I don't have a need for a more automated solution.
    Also I think I understand the logic behind effectors better now.
     
    MelvMay likes this.