Search Unity

Is there no collision detection function in Unity?

Discussion in '2D' started by LFGJ, Nov 15, 2019.

  1. LFGJ

    LFGJ

    Joined:
    Apr 29, 2017
    Posts:
    2
    Hi, people!

    I am new here and I don't know the correct way to introduce myself, so I will go directly to the problem (and my grammar is not that good as you can see...)

    I am trying to create a 2d platformer game and code the physics of my game, but I am struggling at trying to implement a function that detects collision whenever I call the function.

    As I can see, the collision detection, on Unity, is asynchronized with the frames, that is, onCollision functions are called whenever the engine wants and before the Update(), which is a big problem to what I am trying to do.

    I've tried a lot of methods like:
    • Creating a variable isColliding for checking if there is a collision on Update(), but it was not synchronized with the frames
    • Using 3D Collision to try Rigidbody.SweepTest, which was a bad idea and barely worked.
    • Using concurrency methods like mutex/lock/monitor to execute my physics code section, but the collision and the physics code get slow.
    • Implementing my physics code in FixedUpdate(), but you already know what happened, and any "solution" wasn't a real solution.

    I already tried to create my own engine to my game, using OpenGL, but it is too complicated and it takes a lot of time to complete the engine. SO, what I can do now is try to implement GJK algorithm for collision detection whenever I want, inside Update(), and GJK is the best and the fastest algorithm to detect collision/distance vector/minimum translation vector in whatever dimension you want.

    I am feeling limited and I am losing my hopes on collision system of Unity because I do not want to use "hacks" like raycasting EVERY S#!$ or use force and velocity from physics system. I shall say the physics of my platformer game is not simple as other platformers.

    Could ANY HOLY BEING help me and give me a solution, or the right way to implement collision system?

    I will be grateful for any intention of help, and I already thank anyone for the attention!
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    You're indicating that what Unity provides isn't enough but don't ellaborate why or exactly what you want and it kind of seems you're potentially confused on what Unity offers and how it works but maybe if you ellaborate on exactly what it is you want then it'd be easier to help.

    This isn't true. At the end of the simulation step the script callbacks are made informing you of what the current state is i.e OnCollisionEnter/Stay/Exit2D and OnTriggerEnter/Stay/Exit2D. By default the simulation step happens automatically during what Unity calls the FixedUpdate which is set at a frequency you can set in the "Project Settings > Time > Fixed Timestep". All this really is, is that each game-loop (per frame) and prior to rendering, Unity decides if enough game-time has passed (fixed-update time) and if so it calls the fixed-update and takes the fixed-update time away from its total. If there's still > fixed-update time left it'll call it again.

    If your fixed-update frequency is 60hz and your frame-rate is exactly 60hz then you'll get fixed-update -> update -> fixed-update -> update etc however if your frame-rate is 120hz then you'll see fixed-update -> update -> update -> fixed-update -> update -> update etc. My point of ellaborating this is that fixed-update won't be called at that frequency but will actually be called when total elapsed game-time exceeds the fixed-update. The simulation is always asked to simulate that fixed-update time. All the physics sees is calls to step that period of time.

    You are free to run the simulation at whatever steps you like whenever you like. If you turn off Physics2D.AutoSimulation either in the Physics Settings or via script then you can manually call the simulation step with Physics2D.Simulate passing the delta-time you'd like to simulate. This can be per-frame if you like. Note that as with auto-simulation (which just calls this for you with the delta-time as the fixed-delta-time) that this performs the simulation then performs the script callbacks for OnCollision/OnTrigger. In other words, you have full control over when this runs and can even run it per-frame if you wish (variable frame-rate simulation).

    If you look at Physics2D you'll see a wealth of configuration options and a set of static methods allowing you to perform queries (overlaps & casts), grabbing contacts, querying contacts etc. There are also calls like Physics2D.Distance which will give you details on the spatial relationships between two colliders. The results include nearest points, normals, distance including overlap state (negative distance) etc. There's also convenient methods on the Rigidbody2D to automatically iterate all attached colliders such as Rigidbody2D.Distance. Using these you can create your own collision response using Kinematic bodies for instance.
     
    Last edited: Nov 15, 2019
    vakabaka, MisterSkitz, LFGJ and 2 others like this.
  3. LFGJ

    LFGJ

    Joined:
    Apr 29, 2017
    Posts:
    2
    Thank you so much for the help! But I still have some questions about the physics system. I did not try that yet, but it seems Physics2D.Simulate needs a good time to process, and it may fail sometimes.

    [QUOTE = MelvMay] if you ellaborate on exactly what it is you want then it'd be easier to help. [/QUOTE]
    So, what I would like do to is, actually, to not feel limited, so I can do a lot of things I planned to do, but I have a simple problem to you:

    I have a Pentagon that follows the mouse position and a diagonal Barrier in a form of a stretched diamond.
    • When the mouse is in a position such that the Pentagon does not collide with the Barrier, the Pentagon will be at the mouse position.
    • When the mouse is in a position such that the Pentagon does collide with the Barrier, the Pentagon will translate at the minimum vector such that the Pentagon would not collide with the Barrier(MTV).
    My solution to it was:

    Code (CSharp):
    1. void Update(){
    2.     Pentagon.position = mouse.position
    3.     MTV = MTV_Algorithm(Barrier, Pentagon)    // MTV is Vector2.zero if and only if there is no collision
    4.     Pentagon.position += MTV
    5. }
    I am thinking about what if I do a physics code that I would like to translate the collider, and then check the collision to use in a "passing through the wall" power, or to move an object and do the physics before the draw call is called, preventing a bad view of an object entering the wall and repulsing a lot of times.

    I will consider what you said: "you're potentially confused on what Unity offers and how it works", and I am starting to think that the way I am trying to do is not the "fastest" way, so that is why Unity is not doing O(n^2) collisions.

    And again, thank you so much for giving me a help!!! (and for the patience hahaha)
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    This call cannot "fail". As I said previously, this is the exact same call that Unity makes when auto-simulation is on and by default is called at 50hz (or whatever the fixed-time is set to). It's not some "special" simulate call and when you turn-off auto-simulation, all that happens is that Unity stops calling it for you so it won't fail or take any more time than the usual simulation tick. Sounds like you're perhaps just not following what it does but it's hard to tell without examples of how you're using it.

    Following the mouse/dragging is pretty trivial but you've used words like "not feeling limited" which seems to indicate you're saying Unity physics is somehow limiting you but again, you've not actually said what's limiting or going wrong. I can see the pseudo code you put in there but I'm not sure how to help you. There are lots of queries that I've already mentioned above that would help you achieve this kind of kinematic movement but also the automatic collision response would do what you want too with almost no code.

    There's no point in me showing you how to do this until I have some sense of how much you know. Have you been through any 2D physics tutorials? Do you understand what the queries provide?

    Ignoring that, I'll give you a link to a test project that shows (along with a lot of other stuff) mouse-dragging/following here.

    MouseFollow
    MouseDrag

    The above is only one of many ways of doing this. The above method means that the item following the mouse isn't forced into overlap because the TargetJoint2D it uses simply tries to move the body to the mouse position but the collision system stops it from overlapping.

    Note: It's a small but super important detail but you should not be touching the Transform with physics. You add a Rigidbody2D and then go through its API to get movement (changes in pose). Modifying the Transform is bypassing the physics system and is slower. If you want to ask a Rigidbody to change pose you should use Rigidbody2D.MovePosition and Rigidbody2D.MoveRotation.

    This example might not be obvious but it causes a body to follow a complex curve using physics and correctly handles collisions (all automatically). It uses MovePosition mentioned above.
    FollowCurve

    If all the above is confusing then I would really recommend going through some tutorials, assuming you've not already.

    Hope this helps.
     
    Last edited: Nov 17, 2019
    blu3drag0n, vakabaka and MisterSkitz like this.