cjddmut / Unity-2D-Platformer-Controller

A customizable 2D platformer motor that handles mechanics such as double jumps, wall jumps, and corner grabs. Includes a player controlled prefab that can be dropped into any scene for immediate support.
MIT License
877 stars 163 forks source link

[Question] Getting characters to act as moving platforms while also inheriting movement from other moving platforms #31

Open McGunn opened 9 years ago

McGunn commented 9 years ago

I'm working on a game that requires there to be moving entities or objects that act as moving platforms. But those entities need to also be affected by moving platforms like the player is. This means that the player could toss a stack of boxes onto a moving platform, and the stack will all just move along nicely.

So technically this means that these entities need to be in the MovingPlatform layer. When I move them into that layer they detect themselves for collisions and just float in the air basically unable to move anywhere. (Right now I'm using the Simple AI Ninjas to test this)

I've tried going through the PlatformerMotor2D script and doing a little trick. I switch the layer to a new layer that I called TempLayer before running all the checks, and then switch back to the original layer. This now makes the characters stay in a falling state with the falling animation and "technically" causes their vertical speed to increase(unlike before when they would stand in the air) but they still do not fall, and seem to be detecting a collision with themselves.

If someone could point me in the right direction I will run with it and I will share what I come up with.

llafuente commented 9 years ago

I have an idea that may work. Moving platforms move horizontal/vertical I would try to add a new one that follows a motor + offset + offset angle

There is a minor problem, you have to disable collisions between the motor and the platform if they collide, i don't know how.

In your specific case a box is both a motor and moving platform of the same size. At the end: motor will collide with moving platforms and Moving platforms with motors

I think this would do the trick :)

cjddmut commented 9 years ago

The most important thing about moving platforms (as far as the motor is concerned) is getting the delta position before the physics tick.

It sounds like the boxes are simply a moving platform themselves that need to be able to land on other moving platforms and move with them. So give them a MovingPlatformMotor2D component and write a component does handles the behavior of stick on other moving platforms (can do it similarly to how the motor does it). I don't think you'll have the experience you're looking for by giving the boxes a PlatformerMotor2D component, it really isn't set up well to collide with other motors.

If you need the boxes to have more complicated physics (like if they were using Unity's physics engine) then that may work out ok as well if you give a kinematic rigidbody to the moving platform and a normal rigidbody to the boxes. You'll have to let the physics tick to its job then update the delta position in the MovingPlatformMotor2D. This might cause a frame issue with the motor as it runs before the physics tick but you could move all the motor logic to a coroutine that uses WaitForFixedUpdate and that may solve that issue.

I do intend to improve the moving platform experience for version v0.5 which might help out with a bit of this stuff as well. Please respond with questions or if any of this was confusing :)

McGunn commented 9 years ago

I don't want to use physics at all. I've built an entire system like the one I'm speaking of in Game Maker Studio, but that software has too many issues to try to develop an entire game in it. Basically I want just about anything in the world to work like a moving platform, whether it's a box that can be picked up and thrown, a turtle that walks around that can carry things on it's shell, or anything in between. I want everything to be able to move around with the same accuracy that the player does, and to clamp to surfaces the same way, handle slopes the same way, and stick to other moving platforms the same way.

I'm using the Ninja Simple AI Scene to test this. If I simply put those Ninja's into the Moving Platform layer, and give them a MovingPlatformMotor2D they work perfectly as moving platforms. However the one and only place where I'm having an issue is that if I enable their own detection of the Moving Platform Layer as Moving platforms, then they seem to detect themselves as moving platforms and they will never fall. It's like they're clamping to themselves. I guess the simplest way I can put this is: Is there a way to make PlatformerMotor2D ignore "this.gameObject" when checking for collisions? Even when the game object is part of a layer that PlatformerMotor2D is considering for collisions.

cjddmut commented 9 years ago

I see, you're correct. It's not supported for a motor to ignore itself. This was a decision for optimization. But it isn't too hard to modify the source to work the way you'd want it to.

When the motor is checking it's surroundings it will do different things depending on what is supported (one way platforms, slopes, moving platforms ect...). For example, with one way platforms disabled, the motor will box cast to detect but just care about the first Collider2D it hits. In your case this will be the collider of the motor. If one way platforms are enabled, the motor will grab all the colliders and care about the closest Collider2D that isn't an invalid one way platform.

You can modify the source to grab all the colliders, ignore its own collider, and otherwise just care about the closest collider.

Check out the following function in PlatformerMotor2D.cs:

private CollidedSurface CheckSurroundings(bool forceCheck)
McGunn commented 9 years ago

Wow thank you!. The majority of the problem was that I didn't have one-way platforms checked on. How dumb of me to miss that! Now I just have to add in some custom behaviours! Thank you so much!

cjddmut commented 9 years ago

You may still run into issues since it wasn't built around caring about moving platforms that move quite so dynamically.

Keep me posted if you do and I'll put it into the consideration for a feature list for v0.5 :)

McGunn commented 9 years ago

So far my only issue is that even with Platform Effector 2D and One Way enabled, collisions are still detected from the sides. I want both solid and one-way actors to populate this world of unlimited chains of motion-transferring goodness. So basically my issue is that I want anything that is one-way to not push things or block things from the sides.

cjddmut commented 9 years ago

Do you mean how you can catch the side of a one way platform? I set up OWP to work the same way they do in Unity (which doesn't mean it's correct). It's based off of the velocity vector of the motor and the 'facing' vector of the OWP. If they point a similar direction (dot product is > 0) then you pass through the OWP, if they point in somewhat opposite directions (dot product is < 0) then you catch the platform.

So if you're falling on to the side of the OWP that is facing up, you'll catch it.

astraldata commented 9 years ago

Regarding the Platform Effector 2D and One Way, the side issue is fixed with the Surface Arc feature -- please see the following posts:

http://forum.unity3d.com/threads/platform-effector-2d-surface-arc-property.344624/

Due to the newness of this feature, the Platform Motor probably doesn't yet support this. However, a great explanation of the Surface Arc feature is indicated in the link above by a Unity Dev.

llafuente commented 8 years ago

I have done this exact scenario for my game. Without any behaviours at all, I will explain how.

First you need a PlataformerMotor2D (enemy motor). This will inherit movement from any MovingPlatforms. And as a child in the hierarchy a moving platform (enemy platform) NOTE! Both BoxCollider2D cannot overlap! or be real close, give them a little space... I place the platform at the top.

This way I can jump on the top, an it's a movingPlatform (enemy platform) where I'm colliding. And if the enemy motor moves, also de platform, giving you the chain reaction you are looking for :)