a static gameObject, with platform effector2D and box Collider 2D its dimensions are (0.5,3) it is a one-way platform.
A dynamic gameObject, with boxCollider2D its dimensions are (10,1)
When I move object 2 through object 1, at first it is fine, but then object 2 will snap outside of the first object.
After some experimenting, I saw that sorter objects work fine, about 7 is where it starts to get weird.
If you don’t and this is happening then it’s because you’re causing contacts to be regenerated and there’s nothing it can do in that case as you’re stomping over its logic; there’s only so much it can do.
Things that cause contacts to be regenerated are modifying the transform, changing the geometry of the colliders, disabling/enabling, constantly asserting specific properties when they’re not actually changing etc.
I don’t have multiple colliders, on both of the objects.
That means that the problem is that I’m causing contacts to be regenerated and so when the moving object is in the platform, there are contacts.
I don’t quite understand what you mean by “disabling/enabling” and also “constantly asserting specific properties”
All the other are not true.
Enabling/disabling components, especially physics ones.
Components have properties, properties can cause change, constantly setting something can cause this if the property in question causes regeneration of contacts. Some properties check if they are actually being changed and ignore the request, not all do and can.
In the end, the platformeffector looks at new contacts and evaluates them to determine if they have to be disabled. If you cause contacts to be regenerated then these new contacts will be inside collider shapes and not a surface contact. In this case, the normal could be anything and normally always opposite the direction of the nearest surface so it’ll not disabling it and the solver will then immediately move it out of overlap.
Assuming you are, you should not be causing contacts to be recreated. The problem often lies in the fact that devs should not try to modify physics components; the physics system (Box2D) don’t work well when they are constantly changing or in other words, behaviours based upon them (such as this) just cannot work correctly.
In the end, when this happens, look at what you’re doing to the Rigidbodies and Colliders in question. That’ll be the cause.
The platform does have a script that can disable its box collider, but even disabling the script will not solve the issue. And so it is not that.
And disabling the platform’s script and commenting every line of code in the moving object(except of the line of code which stets its velocity to move) and disabling every other component (except of course for rigid body2D, box collider2D etc…), and it is still happening.
I cannot debug it for you unfortunately but you can do some basic tests in another blank scene. Create the same thing there in the absence of everything else, even better a blank new project.
Beyond that, I can’t do much to help.
Note that effectors have not changed in years and this is a basic feature of this particular well-used effector so the likelyhood of it being a bug is remote.
If you have a simple reproduction project then I’d be happy to take a little time to look at it for you.
I know it has been a while, but still.
I have tried the bug with the most simple objects, they have nothing but the what they need(rigidBody2D, box collider etc.) and no scripts, and it still happened.
I didn’t mention that the platform already starts inside the one-way platform, which that was the problem.
If the platform was half-way in the platform, it will happen, if it is only a bit inside or out side completely then it will not happen, this is why when the object was small, the bug didn’t happen, it doesn’t matter that it was small, but the fact that there was less “stuff” through the platform, made it do so.
But it is not as simple as not putting the object through the platform in the scene, because the platform can go both ways, so the player can do make the bug happen pretty easily.
The PlatformEffector2D looks at the collision normal to determine the one-way action. If you’re starting with contacts inside a platform then it’ll use the collision normal of that but this clearly won’t be a surface contact. The normal will point away from the closest edge (this is just pure physics). If the normal is pointing away from the one-way surface then you’ll get the one-way but if it’s pointing away from the other then it won’t disable the contact and the solver will push it out.
In the end, it’s not magic, it can only use the information is has.
You are free to look at the contacts yourself, the effector sees the exact same contacts as you do but there should be no reason why you’re creating something inside a platform. If it’s that you’re moving something fast and using Discrete then this is why you’d use Cuntinuous.
To add, this is not a bug.
This is the code:
// Process one-way collisions.
// If we're contacting anything outside the surface then we ignore the contact.
const float surfaceDot = b2Dot(collisionNormal, localUp);
const float surfaceAngle = cos(Radians(m_SurfaceArc * 0.5f));
if (checkOneWay && !CompareApproximately(surfaceDot, surfaceAngle) && surfaceDot < surfaceAngle)
{
contact->SetIgnored(true);
return;
}
I’m assuming that the code is unity’s code, and not the code to fix this “problem” as you said, not a bug.
correct me if I’m wrong about that assumption.
As I said, the platform can go both ways, and so the player could make this easily, if he will get the platform inside the one-way, with a button and then use the button to get it out, and it will happen, this could happen because the one-way can be closed/on.
I could make it that it does not happen, by careful level design, but actually solving it will be much better
Yes, it’s the code used as I described above how it all works.
I’m really not following what you’re saying here. Who solving it? This isn’t a problem you should have. In the end, it won’t work if you’re doing strange things such as moving things into overlap and expecting it to “just work”.
The platform can go both ways, and the one-way can be opened and closed, when it is opened, the is no collisions on both sides.
And so, if the is a platform, and a one-way on the same y level and a button to open/close the one-way and a button to move the platform right/left, it could happen.
The player can open the one way, move the platform inside the open one way, close the one way, and then move the platform out side of the one way. This sound complicated but it is really not.
Turning one way platforms on/off is normal, which that makes the entire problem. (I turn it off/on by disabling the collider, that could maybe be the problem).
It doesn’t sound complicated, it’s just not clear as there’s no image to show what you mean and you’re describing it using your own terminology.
Like the above, I’ve no idea what this “platform” is or what “both ways” means or how that relates to the issue. I describe using discrete/continuous movement above but you’ve not responded to it.
“Opened and Closed”. Again, not sure what that means. Maybe you mean enabled/disabled and it’s this kind of terminology that is confusing things.
I’ve described in detail a few times how the one-way works (even shown the actual code that handles it) along with what it won’t like you doing (creating overlapped contacts) and what to do to ensure you don’t create contacts inside your platform; this’ll be the problem.
I can’t really help much more than this, especially when you don’t really respond directly to the specific things I suggest such as using continuous etc.
Closing and opening the one-way is achived by disabling the collider
public bool open;
collider.enabled = open;
I’ll show with pictures:
The white is the moving platform, the red is the one way. The platform is going to the right, and the one way’s collider is pointing to the right, so the platform can go past it.
Now, the platform is going to the left, because the player pressed a button, which made the platform go the other way. The one way is now yellow, because the button also opened(the collider is disabled and the platform can go past it).
The platform is part way through the one way.
The player pressed the button again, The moving platform is going to the right, and the one way is closed(the collider is enabled). Now the thing will happen.
I can’t prevent the player from doing this, unless if I don’t make levels with these conditions, which I will do, but only if I MUST.
Hope you understood. If there is nothing I can do to solve this, I will not make levels with these conditions, and as stated, I don’t want to do that.
So you’re creating contacts in overlap. They are not colliding with a surface, they appear in overlap. Don’t enable it if it’s in overlap. You can easily check this with a query.
You’re essentially causing this problem by disabling/enabling the collider so it looses all its state and you need to find a mechanism to avoid that in your design.
The platform effector cannot do its job if it’s being enabled/disabled like this is all I can really say.
I will add that it’s not clear why you’re using the platform effector to do this. It seems like you could simply use a query to detect things that block the “white platform” based upon rules you set.
For instance, if you perform an overlap check first and you’re overlapped with the “red/yellow” thing then I believe you want it to ignore the “one way” rule so just move it in that case.
If it’s not overlapped already then query using “Collider2D.Cast” for the platform in its current direction of movement * time-delta filtering with a mask by things you want it to detect. If it detects nothing then you can mvoe that distance. If it detects something then you simply need to know if it should be blocked or not. If it’s blocked then only move it to just touch it as per the results of the cast.
The platform can/should be Kinematic. Nothing will need to be disabled/enabled.
Use queries yes, you don’t need to use a PlatformEffector2D to determine whether you should stop moving the platform or not. Platforms are typically Kinematic anyway.
How can queries help here?
I once did it by storing the one way’s collider side, and if the platform detects the other side, it will skip it(it is an array of raycatshit2D), and the collision will be detected using the next entry of the list. Is it optimal?