Custom Character Controller built from scratch for Unity. Fulfills all common character controller functions such as collision detection and pushback, slope limiting and collider ignoring. New features include the ability to rotate the controller to any angle, sophisticated ground detection, ability to clamp the character to surfaces, and detailed collision response messages. All functions are fully exposed and editable. Also includes the SuperStateMachine, a finite state machine designed to interact with the controller.
GitHub repository of the project to download or contribute to
Note: The GitHub repo is brand new, and is the first open-source project I’ve maintained. For those more experienced than me at this, any suggestions on how to improve it are welcomed.
Example Unity Project containing demo scene (same project as on GitHub)
Unity package containing essential code (.unitypackage file)
Changelog
2.0.0: Added a BSPTree to replace RPGMesh, as well as new grounding techniques and recursive collision detection | Erik Ross
Added support for the CapsuleCollider primitive collider | Moodie
1.1.0: Added support for a fixed timestep and moving platforms | Erik Ross
1.0.2: Multiple optimizations | iivo_k
1.0.1: Fixed issue where ignoring colliders didn’t properly work | Erik Ross
1.0.0: Release | Erik Ross
For a more detailed changelog, open the README in the package.
References
Uses code from fholm, BitBarrelMedia, and UnityGems. Detailed referencing can be found within the README file of the package.

Hey Drrossen, so I finally got around to looking at your project, here’s what I found. The issue is fairly simple overall: the SCC and the NetworkMovement script you have (which I assume is Gena’s CSP script) run on different Update loops. When the NetworkMovement sends back it’s data to the client, the client attempts to reconcile it’s position with the server. However, at the same time the SCC runs it’s own grounding and collision logic, resulting in a bit of a clash. In order to get this to work properly, you’ll need to sync up the SuperUpdate method with whatever movement prediction/reconciliation you’re doing, which is what I’ve done for my project.
If you’re just looking to prototype out a project, you don’t really need prediction/reconciliation that much. By and large it’s a tool to prevent cheating (although it’s also used to keep players in sync), and typically people don’t cheat during the testing phase ;D. As well, it’s quite easy to add in later on in between current network logic, which is also what I did.
Hey Roystan, thanks a lot for the SSC!
I’m also working on a networked project, would you mind to share your solution in more detail? I’m not quite sure how I should go about syncing the NetworkMovement with the SCC while still using a StateMachine. Do you sync the PlayerState from the server and then call the entire SimpleStateMachine-update for every call of the Move-method? (talking about the “Move” from Gena’s CSP)
Hey Leonardo, you’re my fav ninja turtle fyi.
Anyways. Gena’s main technique is very similar to mine. He gathers all the inputs in the Update, and then runs his logic in FixedUpdate. Here’s what I do, and how it fits in with the SCC (and the state machine):
I gather inputs in Update and push them to the server. That’s all that’s done in Update. On the server, each FixedUpdate tick I read the inputs and run them. Here’s where the SCC fits in. Because the SCC runs on it’s own Update loop (SuperUpdate, which itself is called from Update), this would cause problems with (most) networking solutions. So instead, I disable the main SuperUpdate (for the server characters) and instead run it manually, through a method called SuperCharacterController.ManualUpdate(float deltaTime). Running this runs the SingleUpdate method that’s in the current version of the SCC, except it sets the deltaTime to the provided value (this is necessary as you need to know how much time elapsed during the input the player provided). I am following Valve’s Source Multiplayer framework.
I seem to get asked about this a fair amount these days, so I’ll push the SCC changes up to GitHub this week. It’s not an invasive change at all—there’s just one boolean that decides if the controller is updated normally or purely manually. Having the ability to manually run updates is also extremely useful for reconciliation, where the server sends back the authoritative position as it allows you to “re-run” a bunch of inputs all in one frame.
I hope I answered all your questions, if not please comment back.
Erik.
Haha, thanks for the fast and elaborate answer! I was experimenting yesterday and tried to make a ManualSuperStateMachine. I’m pretty sure the main thing I missed was the deltaTime, I could just calculate it from the timestamps of the inputs I guess. Looking forward to that Github push so I can see a well-tried solution.
Aight so I looked it up turns out Donatello is actually my fav ninja turtle. Sorry bud.
So I pushed the change to the master branch on the repo. It’s not a large update, but it’s one that I’ve found useful and elegant. There aren’t any examples yet, but it shouldn’t be too hard to figure out. I’m thinking of putting up an example of my network controller, but as it is right now it’s specific to my project, so it’ll take a bit to make a generic one (and maybe would be more fitting as a separate repo).
Hi, love your system but I have a few inquiries.
One, how can I have the PlayerMachine cancel out velocity when colliding with geometry? Out of the box PlayerMachine keeps trying to move in whatever direction until natural velocity decay takes over and the player’s inputs are accepted again. This is most noticeable when jumping into a low ceiling. The SCC will “stick” to the ceiling until the y velocity becomes negative. I am making a game where the player will be pushed around a lot so this is a big issue!
Two, occasionally when walking off of an edge the PlayerMachine will not correctly enter the falling state and will just “snap” to whatever floor is below. I can’t seem to find any particular pattern to this. I am using ProBuilder for my level geometry if that helps. (Its just mesh colliders)
I stream my project on twitch so come check out what I’m doing if you’re bored. ^_^ http://www.twitch.tv/bamboy360
Hey Stephan,
You can access the collision data of the SCC through the collisionData property, which will tell you what the controller collided with during it’s last update. You can use this to determine if you have contacted a wall or ceiling and adjust your moveDirection velocity accordingly.
For the other problem, this is the second time I’ve heard of people having issues with the SCC and ProBuilder, but I thought I had fixed them. Do you have a video or gif showing the error?
Erik
Its hard to reproduce as it isn’t consistent. I recently made a new level using simpler ProBuilder shapes but a lot more of them, rather than one or two very complicated shapes. I think this has helped, but every now and then it still happens.
I’ll look into it either way. From my last experience debugging a ProBuilder issue, it looks like at runtime ProBuilder objects function just like any other mesh collider. I’m assuming that it’s due to how lots of people use ProBuilder for prototyping out scenes quickly and end up with somewhat wonky geometry, with sharp edges and whatnot, that expose (literal!) edge cases. I have a fairly good idea what could be causing this, but could you screenshot your level in the area it happens?
Hey again. A few updates.
While trying to make my velocity cancel out when colliding with something, I ended up going back to your demo project to test it on various surfaces in your scene, and low and behold, the snapping to the ground bug happened. It does not seem to be probuilder related. I’m using a slightly modified version of your player machine script. I’m at a loss. Again I don’t feel a screenshot would help because it does not happen consistently in any area or with speed. It seems to be random.
While trying to make my velocity cancel out when I collide with something I ran into a problem in SCC.cs where you were calling ‘collisionData.Clear();’ at the start of your function RecursivePushback(). This was making it so that collisionData was empty 90% of the time and other scripts could not read from it. I fixed this by calling it in SingleUpdate() right before RecursivePushback() instead. I have not seen any issues from doing this. Consider making this change live?
As far as canceling out the velocity variable itself within PlayerMachine, I did the below at the start of LateGlobalSuperUpdate(). It seems to work very well for my purposes but I have not tested extensively. Consider making this change live?
//Stop moving in the same direction that was collided with
if( controller.collisionData.Count > 0 )
{
foreach( SuperCollision c in controller.collisionData )
{
moveDirection = Vector3.ProjectOnPlane(moveDirection, c.normal);
}
}
Hey Stephan,
I’ve pushed a change fixing the collisionData being cleared to the master branch. I’m not sure right now about adding the velocity cancelling, since ideally the PlayerMachine was intended to be as basic as possible to demonstrate the controller, but I don’t think that block of code would really push it over the edge. I’ll probably end up adding it in a future commit.
For the clamping issue, I had another user run into the problem, and I wrote a large post about it here. You can look at the branch I pushed up for him and see if it solves the issue, but it’s not the most elegant fix, and I’ll be looking more into the overall problem further to find the best solution.
Also, if you do find other bugs or make improvements to the controller, feel free to pushing your own branches to the repo, since I respond to the pull requests pretty quickly.
As always, thanks for the feedback.
Downloaded your package from GitHub, but i can’t seem to find a way to set it up. Any help?
Once you’ve unzipped the folder, you can open it like any other Unity project.
So, I was moving forward with my project, and I have objects that the player can throw (using the Rigidbody component). However, I’m noticing that they’re not colliding properly anymore. Does implementing your system override the natural physics built into Unity? For example, my player throws a ball, but the ball just goes right through the ground instead of colliding with it as it should.
No. The SCC doesn’t modify the way the physics work at all, and interacts with them fine. The sample project on GitHub does have it’s own Project Settings, so if you imported your project into the sample, you would lose whatever current layers you have setup. In any case you can check Project Settings->Physics to make sure the proper layers are setup to collide. If not, build a new scene and test if something within the scene has broken.
Hey Roystan,
I’m in the process of transitioning from Unity’s CC to your SCC and have a few questions I hope you can answer.
How am I expected to respond to collisions, with enemies that cause a recoil, for instance? With Unity’s CC I use OnControllerColliderHit() and build some lists of what was collided with this frame. From that I can ascertain what is in an “Enter”, “Stay” or “Exit” phase of a collision. I see that you expose “collisionData” in SCC. Is the idea that I iterate over this at the end (or start) of a frame and perform some similar logic? What point in the Update phase would be the best to do this?
In your demo you have a CapsuleCollider on the Art node. I think I read somewhere that the spheres on the SCC are used for collisions from the SCC into other objects, and the capsule is used for collisions from other objects into the SCC, is this correct? Could you elaborate when I should be using “collisionData” in SCC versus the OnCollision methods that would fire from the CapsuleCollider? I imagine there are specific use cases you had in mind for each?
Is it OK to have a kinematic RigidBody component on the same node as the SCC? This is how I had it setup with the Unity CC.
Have you ever seen the SCC fall through a MeshCollider? I have added the BSPTree onto the same GameObejct as the MeshCollider. My character now runs on the flat part of the mesh OK, but as it starts to slope downwards, the SCC falls through the mesh. I have yet to debug this, but maybe you can think of a reason? Does it have problems with particularly sparse or dense MeshColliders? I’m using Unity 4.2.3f1, it could even be a physics bug I guess. Here is an image of the mesh collider. The collider itself is just a loop that goes round the entire terrain, it doesn’t have a front or back.
http://postimg.org/image/zcs088b63/
My character falls through roughly at the red X.
I have read through the entire PDF that comes with the package and looked at the demo scenes, but couldn’t find any info on the above. If I’ve missed something though, please just point me towards it and I will read some more
Thanks a lot,
Niall
One other question that has just popped into my head. Should I be aiming to have the sphere based capsule approximation (on SCC) and the actual capsule collider (on Art node) matching up exactly, or should one of them be slightly smaller and “inside” the other?
Any tips for building the sphere based approximation for best results? My character is much slimmer than your test capsule, so I ended up using spheres with a radius of 0.18. I have used 5 spheres total and have tried to spread them out by the radius (your demo used 3 spheres and spread them out in a similar manner it seemed). The head sphere is intersecting a little bit more with the sphere below it so I could match the character height better. I have marked the bottom and top spheres as Feet and Head, and left both boxes unticked for the middle 3 spheres. Does this all sound right?
The original issue I had with falling through the terrain was actually caused by a missing BSP component. I had added the BSPTree for testing, but my terrain rebuilds whenever it is selected and I had inadvertently removed it.
Now that I have that sorted, I as still seeing my character fall through the MeshCollider occasionally. Usually when he should be landing from a jump.
I think this is due to the use of Physics.OverlapSphere in RecursivePushback().
If the sphere radius is small enough and the character is moving at a large enough speed, the sphere will teleport from one side of the MeshCollider to the other. As the surface of the terrain has no thickness, when the sphere is “inside” the terrain, it doesn’t cause an overlap to occur and so we never do any pushing back to keep him on the surface of the terrain.
I have reproduced this quite easily in your test scene by just changing the sphere radius to 0.05 and spacing them appropriately. When you jump off the starting block onto to the ground below, the character falls through. It isn’t 100%, but if you run around in the pit for a while, you’ll fall through as well pretty quickly.
For my game I want to use a sphere radius of 0.18. My game scale is set up to reflect real world units already. The proportions of the character are fairly realistic and I want to have the capsule to just be slightly wider than the torso when viewed side on.
In my game, the player can easily hit speeds of 25 m/s when falling from a platform. By my calculations, I would need to cap to about 10.8 m/s to avoid the sphere moving by more than it’s radius each frame.
Even using the sphere radius of 0.5 in your demo, this means that a character can’t move at any more that 30 m/s before we start to see potential issues. I think there will be less issues with Sphere and Box colliders etc as they have an actual volume, mesh colliders on the other hand…
Is there any reason that this call to OverlapSphere couldn’t be replaced with a cast from the previous known position of the sphere? We can assume that in the previous frame, none of the spheres were inside anything as we would have ensured this in the previous frame with RecursivePushback().
I guess another object could have moved on top of the character actually… balls. Maybe we need to check both a SphereCast and an OverlapSphere to ensure we catch everything (even if we still might not catch MeshColliders moving on top of the character. People tend to sue them for static objects though, so we might get away with it.
Any ideas on how best to work around this?
Thanks a lot for your time.
Hey Big N, several questions here, I’ll try to make sure I address all of them.
The SCC doesn’t have anything directly analogous to the CC’s OnControllerColliderHit in the sense of a callback. I decided to avoid having a callback since the SCC already had a fairly strong structure in terms of the order that operations are performed in, and that an array of data would be more useful.
Speaking of useful: you iterate over it whenever you need to know if you collided with something, or what kind of thing. It tells you which collision sphere (on the SCC) you hit, and a bunch of data where the collision occured and with what object. So to answer your question: you can iterate over it whenever you want, but I’d recommend only doing it during your SuperUpdate callbacks.
If you’re attempting to build a system on top of the SCC that implements an Enter/Stay/Exit functionality, this is definitely possible. Again, I’d recommend either doing this at the beginning or end of your SuperUpdate callback.
You are correct about the purpose of the Capsule Collider: it’s just there to give other objects something to collide with.
You can definitely have a kinematic rigidbody on the SCC node (in my experience), but I’m not sure what purpose it would serve.
I’ve always had the Capsule Collider match up exactly with the spheres, but there isn’t really any reason I can think of that they would be required to be.
Your setup with the spheres sounds correct. In retrospect, I’m thinking I should just set the feet and head to be the lowest and uppermost spheres at runtime, since I’m struggling to come up with an application where you wouldn’t want this to be the case.
Bear in mind when falling vertically towards a mesh collider, the distance you can travel without clipping through it would be equal to the height of the entire controller, not just a single sphere (since even if only the head is touching the mesh collider, the entire controller will be recursively pushed back onto the surface). But that doesn’t really address the core issue here.
First off I’d make sure you have Fixed Time Step enabled and Fixed Updates Per Second set to something reasonable. That way, the SCC is frame rate independent. I typically set it to ~60, and with a speed of 25m/s you’d be looking at moving about 0.417 meters per frame…which probably would push the limit a bit for your case, given that your controller sounds very small (although the absolute size is irrelevant, it’s just the size compared to the velocity that matters).
In terms of robust solutions, I briefly touch on this in one of my articles at the end. In general, the best way to implement this would be on the assumption that it would not be successful 100% of the time, since CapsuleCast and SphereCast both have the issue that they fail if there is an object intersection their origin. But by and large, that would be okay! The overwhelming majority of the time the recursive pushback works to free the controller from any colliders. Off the top of my head the best way to do this would probably be to throw it at the end of the pushback method, as a sort of final check to ensure we did not clip through anything.
In any case, it’s something to work on when I get the time. As well, I’ll also update the documentation about the collisionData stuff, since it seems I only have one or two brief sentences about it that could stand to be a bit clearer. Hopefully I’ve answered all your questions here!
Haha, right back at ya, Big R!
Thanks for addressing each question, really appreciate the support.
I am not currently using the fixed time step mode.
None of your demos seem to use the FixedTimeStep mode from what I can see, am I right in thinking that?
Is it expected that I just run my entire PlayerUpdate using the fixed system, but instead of using Time.DeltaTime in the scripts, use SuperCharacterController.deltaTime?
Hmmm, I see what you are saying about the RecursivePushback and the entire capsule height having to pass over in order to phase through. I guess the issue could be that it’s pushing back down instead of up? If we managed to catch the overlap on the head sphere (or any sphere in the top half of the capsule), the path of least resistance would be to move the controller down I’d imagine? Haven’t quite understood all the internals yet, so just guessing really at this stage. Is there any bias to push upwards given that is the way the normal of the MeshCollider would be facing.
I also noticed that ProbeGround only uses the Feet sphere. In the case of ProbeGround, I imagine that it would only take twice the radius of the capsule to phase through. This could mean that the ground variables don’t get set correctly in this case. What happens if the SuperGround objects didn’t register the platform, but then the RecursivePushback() detects an overlap?
I will continue to debug and see if I can figure out any of the above and the root causes of the falling through issue. Perhaps using the fixed timestep will sort it out…
As an aside, any advice for treating the bottom of the capsule like a rectangle?
I leave Fixed Timestep disabled for the demos since you tend to want it disabled for any debugging. It can be difficult to narrow down an issue when multiple updates on the SCC are being run in a single frame. For a “finished” testing, it’s almost always a good idea to have it.
And yes, you should always use controller.deltaTime in your SuperUpdate callback. Even if Fixed Timestep is not enabled, controller.deltaTime is just set to Time.deltaTime.
The pushback happens in the direction of the normal of the triangle that the closest point lies upon, so it will never force itself further downward.
If ProbeGround misses, it assumes that the SphereCast origin was clipping a wall (or something) and attempts a raycast downwards instead. If that fails, it debugs out an error and no action is taken. Here’s where things can get a little woolly. In theory ProbeGround should barely ever miss: since Pushback is run right after SuperUpdate, the controller should never be clipping an object when ProbeGround is run due to your character’s movement logic (unless you clipped through an object, like in your example). In practice, on rare occasions it looks like ProbeGround’s initial spherecast fails while on the edge of a cliff, the raycast kicks in and it clamps you to the ground at the bottom of the cliff (although I thought I had resolved this!).
For your case it might just be clipping. Try Fixed Timestep, or reduce your character’s gravity to see what’s up. If neither of those work let me know!
Great. I think switching to fixed timestep has resolved a lot of my issues.
I have also upped my sphere radius a little to 0.21, this should let me have my terminal velocity of 25 m/s at 60hz.
Some of my remaining issues are caused by having platform objects that use multiple box colliders along the length of the platform (they are resizable in editor and made of pieces at present). Due to the way the pushback works. I will need to combine the colliders into one I think.
Did you see my previous question about treating the bottom of the capsule more like a rectangle?
The current issue is when I run into a crate, I zero out the horizontal velocity. When my character jumps, I give him a small horizontal velocity to force him forward (but stop him zooming over the top at running speed) and collide with the top edge of the crate. In the old system, this was enough to place him on top of the crate and he would then start running again. With SCC, the collision point is too far from the centre of the capsule, so this is treated as not steady ground and the character just falls to the ground below.
I have tried to modify the variables used in OnSteadyGround() (groundingMinPercentFromcenter and groundingMaxPercentFromCenter), but this then causes clamping issues when dropping off of ledges
Any ideas on how to proceed from here? Ideally, I don’t want to modify your code too much (if I can help it) to make future updates easier.
My initial thought is to have OnSteadyGround always return true (this causes the clamping issues though). I would try and resolve this by adding in a ClampThresholdDistance, the distance to the ground would need to be less than this value in order to clamp. I would probably also add something so that it could only clamp to the last ground we actually came into contact with. This would prevent the player clamping to the ground below a platform instead of falling towards it.
As always, really appreciate the help. Trying to fit your system into an almost complete game so we can ship it. Fixing the bugs with Unity’s CC was just not possible.
Yeah, gotcha. Since I primarily used the SCC for Mario, once I set those max/minPercentFromCenter vars I more or less forgot about them. Their purpose is to smooth out movement, since without them the capsule will “clamp” down the edge of a cliff until the dropoff finally occurs, in which it will switch to some sort of falling state. The problem is that typically when a character enters a falling state, their y velocity is set to zero and gravity will slowly accelerate them downwards over time. This creates a weird jittery effect, since the capsule’s vertical motion while clamping down the edge of the cliff can be quite fast in comparison to the slow decent of gravity.
Either way it was always intended to be modifiable. The clamping issue you’ve encountered occurs because the SphereCast used to detect ground is slightly smaller than the radius of the controller (or tolerance reasons). So when you’re right on the edge there and you cast down, you completely miss the cliff and clamp to the ground. Although it’s not usually ideal to clamp down a large distance, the SCC is built to not care about that and instead let the PlayerMachine or whatever implementation deal with enabling/disabling clamping…unfortunately, in this case the ProbeGround that causes the issue occurs AFTER SuperUpdate but BEFORE the controller is clamped, giving no chance to the PlayerMachine to sort out which state it should be in.
That’s probably a lot to take in. Anyways, I wrote up a quick fix for this and pushed it to a separate branch, which you can find here. It’s not the most brilliant solution ever, but for a one off thing it should work fine. Basically there’s just a new message sent out, OnBeforeClamp, that lets the PlayerMachine run some logic just before clamping happens. Sometime I’ll write something a bit more robust, but this should work fine for now, allowing the controller to live on the edge.
Hey,
I’m starting a new thread here, as the other is getting quite thin with all the replies.
Your explanation makes perfect sense, thanks for the info. I am slowly building up a good working knowledge of how everything fits together (I think).
I have integrated your SteadyGround branch changes, and as far as I can tell at this stage, it has fixed the issue at the edge of raised platforms, so thanks for that.
So, one problem fixed, but a few more to go. I feel like there could be an end in sight fairly soon though
I have started hooking up the Enter, Stay and Exit logic we spoke about and noticed something curious.
The collisionData list is cleared at the start of each call to RecursivePushback(). This is problematic for me as I am seeing this behaviour:
1) RecursivePushback() is called from SingleUpdate()
2) collisionData is cleared.
3) Character feet sphere is overlapping with the ground
4) The ground collision gets added to the collisionData.
5) RecursivePushback() is called from within RecursivePushback().
6) collisionData is cleared.
7) Feet sphere is no longer overlapping
The end result is that when my code checks the collisionData (in a custom LateSuperUpdate event, fired from the very end of SingleUpdate()) , it is empty.
I have tried moving collisionData.clear() out of RecursivePushback and instead into SingleUpdate. This works a lot better, but I’m still seeing some issues with it.*
collisionData is still sometimes empty, more often when moving down slopes, but it also happens on flat ground. I’m guessing on flat ground it’s due to floating point inaccuracy on the pushbacks so we might get lucky and still be overlapping the last time RecursivePushback is called. For the slopes, it could be that gravity isn’t large enough to move the character down enough to overlap. This makes sense and it’s why the clamping is needed.
Perhaps collisionData could be modified in ClampToGround to add the collision data for the ground (if it’s not already present). I think this may solve the remaining issues I’m actually seeing (but not the potential issues I outlined above).
What do you think of the problem and my potential (hacky?) solution? I think there must be a better way.
I’m wondering if I should even be using collisionData at this stage? Perhaps I should only be looking at currentGround or some other data structure?
CurrentGround doesn’t seem to expose enough information to do what I need though, the actual collider and also the collision point for instance. I can add these things, but just want to make sure I’m not missing anything.
Apart from when the character has “escaped the level”, can I always rely on PrimaryGround being valid? Near, far, step and flush could potentially be null though?
When should I use Normal() instead of PrimaryNormal()?
HitDistance() and Distance() seem to be identical functions.
As always, very grateful for any time you can dedicate to a response, I feel like I’m learning a lot!
Cheers,
Niall
*There are also some potential issues I haven’t actually seen or looked into, but I imagine there would be issues with the same collider appearing multiple times in the list with potentially different collision points as the controller works to untangle the collisions (filtering on add could sort this, but do we want the old version or the new version for the collision data?).
Hey,
The collisionData being cleared was a bug that I just fixed a couple days ago. You can view the fix in the latest push on the master branch. Right now I don’t have time to respond to the other comments, but I’ll definitely get to them later today, just figured the above was important to address quickly.
And yeah, when I picked this styling for the site I didn’t anticipate how quickly the comment section would have the walls close in on it. Planning to change it in the near future to something a bit more flexible.
Thanks for the quick reply. Should have checked the GitHub for fixes before posting.
I have got some info regarding the times when collisionData is empty.
The updates where there is no CollisionData have very very small deltaTimes (the tail end to fill the 1/60th of a second when using fixed timestep). This means that the movement due to gravity is very tiny. I’m assuming that due to physics tolerances, this tiny movement doesn’t cause an overlap and thus no pushbacks are generated.
Not sure how to fix/workaround yet.
Quite easy to repro constantly though, just put:
deltaTime = 0.005f;
at the top of SingleUpdate().
It will all be in slow motion, but it should show the issue.
Are you using collisionData to check what kind of object the player is standing on? If you are, in general it’s better to use the currentGround.transform or currentGround.superCollision type data. This way, it still works regardless of whether the physical controller actually intersected the ground in the previous frame (I tend to zero out my controller’s gravity when he is assumed to be standing on an object, which is done in the PlayerMachine).
This is very good character controller! I have nothing bad to say about SCC. Very goodly optimized. This only needs little bit better documentation. It was little bit hard to understand how to use SCC at begin, but anyway very good work! And this should be included to unity by default:)
Hey shadow, glad it worked out for you. I’ve had a few requests to expand on the documentation, so I’ll probably add a couple more sections to the PDF in the near future.
Figured I should let you know, I updated the docs with a bit of info about the initial setup. I’m also planning to add a new test scene in with some other simple examples.
Hey Roystan,
I know someone asked awhile ago, and you mentioned having planned to give it a shot, but are you still planning to implement the ability to have the SCC compatible with Terrain Colliders?
Already did, a couple months ago. If you pull the latest, there’s a TerrainTest scene.
seems promising.I am implementing it on my project now, though I would like to know if it is mobile optimized? If object is really moving too fast on any one axis ,does it catch collision ? or it misses collision sometimes like Unity’s default controller?
I have not extensively tested it on mobile, but for most of my optimization tests I usually just drop in a ton of dummy controllers and have them walk into walls (usually a mid to large size mesh collider, as they are the slowest collider to do intersection tests with).
It does not have anything built in to prevent “phasing” through walls. It does have an option to run on a fixed timestep to ensure that a certain number of updates are run per second, so that if the framerate drops he won’t just skip forward. Protection against phasing through walls is a feature I’d like to add, though.
Hi!
First off, fantastic work! I’m loving the SCC and the SSM! I’m currently having a minor issue regarding fixed timestep. When enabled, the camera will start micro-stuttering, but only when rotation is performed with the mouse (you can check this in the demo project by simply enabling fixed time step, set it to 60 and then move around the purple box on your left as you enter the testZone; remember to move the mouse on the x-axis as you rotate around it. Observe the corners of the box, they should now stutter).
I believe the reason for this stutter is that the lookDirection variable that the camera accesses through the PlayerMachine is now only updated every 1/fixedUpDate. The peculiar thing is that I have vsync enabled and a steady fps at 60, so they should both really update every 1/60th second? If I disable vsync, the stutter disappears, however I am not sure this solution is the best way about it. I have moved the lookDirection variable to the playercam instead, and have the playermachine retrieve it from there. This has solved the stutter completely, and I believe this is the most clean solution. Alternatively I could simply have lookDirection be updated in an actual Update function in the PlayerMachine (instead of the EarlyGlobalSuperUpdate). I would love your thoughts on the matter.
Thanks for being so awesome!
Hey Metamate, your name definitely sounds like a stuffed animal I could buy on Etsy or something.
I was able to re-create the problem. Often, you tend to want to de-couple the camera from the physics (in this case, the PlayerMachine) like how you did it by placing it in the PlayerCam. However, because the SCC always updates AT least once, it shouldn’t be missing any inputs (as can happen if you poll for input in FixedUpdate). Gonna look into it a bit more, will post back here. Sorry for the slow reply, haven’t been around too much. As always, thanks for the bug report!