• Projects
  • Improving Godot's ClippedCamera node

Hi, kids! It's been a long time since I've posted anything here.

Anyway, I'm sure you all saw akien's tweet a couple of weeks ago where he released the 3.2 "alpha 0" build. It finally fixed the bug in the ClippedCamera node where it wasn't updating the local z of the camera! Excited, I decided to try it out and posted a video of it properly working.

Now, that's all well and good, and should be good enough for most basic games, right? ... WRONG! And let me tell you why. B)

The astute viewer will, upon closer inspection, notice several things wrong with the default behavior of the camera.

-- It does not take distance into account. You can move the ClippedCamera 10 units away, or 100 units away, but it will ALWAYS clip straight back to the player, instead of ignoring geometry between it and the player past a certain distance. That's annoying, isn't it?

-- It does not have any smoothing effect whatsoever. Upon clipping, it teleports straight to the player. Upon going back to a non-clipping state, it instantly teleports back. This is disorienting, confusing, and, as one reddit user described it, it feels like a car crash. Not good! A camera should follow the player, not teleport to the player.

-- It is possible to push the camera through geometry (not shown in video). This just shouldn't happen at all.

So, I took it upon myself to attempt to address these issues, and managed to solve them a bit.

It's a bit complicated, but essentially, here's what I'm doing.

--- I have an array that stores three ClippedCamera nodes, one for each "zoom level". They each are parented to a different target than the player. This was necessary to prevent the camera from clipping back to the player at zoom levels greater than 1.

--- I am not using ANY of the ClippedCameras as an actual camera. Instead, I have a master "view camera" that is being fed the information from the currently active ClippedCamera. This way, no matter what zoom level the player is at, it will respond accordingly. I can also use lerp() to smooth out movement! Neat!

--- I am always casting a ray from the view camera back to the player. If it detects a body between it and the player, it will calculate the distance of the camera back to that body. If it is less than the Max Occluding Distance, it will clip through as expected, otherwise, the camera will STAY BEHIND the body.

Here's some videos on the progress so far!

First Attempt - Just trying to get smoothing working

Second Attempt - Factoring in distance

Latest Attempt - Preventing the camera from pushing through geometry, and demonstrating multiple targets/cameras for the first time

When this is all said and done, I'm locking this up and keeping it for myself and patenting it so I can get rich going to release this on my github page so other people can use it in their games! It's a simple gimbal setup, so you should be able to just drag into your player node and go from there!

I do not have a set release date or schedule or anything. I do have a baby, so my development time is "when I can get to it".

Let me know if there's anything else that you think is missing! And let me know if this is something you would use in your third person games!

Have you considered contacting the dev. who made the node more usable?

The reason I ask is so whether this setup would be improved enough to warrant breaking systems that may have just recently been built. The setup I use meanwhile tends to use spatial nodes as targets rather than the player itself.

@Ace_Dragon said: Have you considered contacting the dev. who made the node more usable?

The reason I ask is so whether this setup would be improved enough to warrant breaking systems that may have just recently been built. The setup I use meanwhile tends to use spatial nodes as targets rather than the player itself.

Good question! I had, in fact, not even thought to contact the dev.

I do believe reduz (Juan) himself is the person who developed it for 3.1 last year, here's a tweet about it. https://twitter.com/reduzio/status/1031910303955595265[tweet]

Later on in that conversation thread, he says this: https://twitter.com/reduzio/status/1031919058336313345[tweet]

So, given that, I'm almost certain he has no intention of updating the ClippedCamera itself, as he has not talked about it since, the docs are barren about it, and there's virtually no indication of any further development on it.

I believe it was his intention to give us a basic camera node which responds to collisions, and then for us to flesh it out from there. Seeing as he has bigger fish to fry, I can't say I blame him!

As a result, I don't foresee any breaking of compatibilities in future versions of Godot, unless they change the very nature of ClippedCamera and how it detects its collisions.

All of that said, I understand your concern. Seeing as I am building this in an alpha build (which is probably insane!), I can see why some people would question me! :p

Reduz was the original developer, but I'm pretty sure there was a patch created by another dev. that changed it to be more usable (which was committed).

So it already received one revision.

The only information I can find is that they fixed its original bug (where it wasn't updating its local Z position, even through code), and are adding information about the node in its current state in 3.2. I can find no mention of adding any additional features to it whatsoever. I can only find Juan's original tweets about it where he explicitly says that it is up to the programmer to move the camera, which I read as he is not going to add any more features to it, at least not for a while.

Regardless, though, I do think my setup will be of value to most people. It's very much emulating a camera system that could be found in a game such as GTA V, for example, which most users may enjoy for their project. I highly doubt that any included node would do that exactly, but I would hope it would offer a lot more basic features than it does now! Not even including any smoothing/damping support puzzles, me to be honest, though I have recently learned that not even UE4 has a smoothing/damping effect on their out-of-the-box camera setups, either!

I'd love to see any signs that they're going to add more features to the ClippedCamera node, but I am not finding anything, which is why I've started this whole thing. If they eventually make ClippedCamera have more advanced features, then great! If not, this setup should work for many versions to come, unless they change the collision detection methods they use in the node itself, which really doesn't seem likely.

I have managed to make some decent progress this weekend despite working almost 60 hours and taking care of a baby!

What did I do, exactly?

  • Removed unnecessary code that was not only redundant, it didn't really do anything.
  • Figured out how to create a "spring arm" sort of device, which works by taking into account the x rotation of the gimbal the camera resides in. This way, as the player moves the camera up, whatever target is currently active for the camera will move ahead, thus allowing the camera to clip through geometry directly above the player. This will work if you are pointing the camera straight down at the player and then move under something.
  • Removed the raycasting to determine the distance between the camera and any occluding geometry, as it was useless since I'm now using three separate ClipCamera nodes, each with their own targets at set distances.
  • And finally, I worked on handling confined spaces (this is where my own "spring arm" came into fruition).

Here's a video, illustrating how it works in tighter spaces, as well as how the target will move back and forth depending on the x rotation of the gimbal!

If all goes to plan, I may be able to have this as a released asset sometime before 2049!

Things I still want to add: - Mouse/keyboard support (currently using my old Xbox 360 controller) - Camera rotating slowly to the player's back when no camera movement input is giving, so that it will always follow the player - Support for different camera heights as well, though not necessary

6 days later

I've made significant progress over the week, after several more experiments.

First, I found that it is much better to go with a one camera and one target system, because adding more targets was getting complicated. Attempting to move the target back to the center of the gimbal depending on the x angle value was, admittedly, a bit of a silly idea, and it didn't work very well because you could end up clipping or not clipping through other geometry at odd times. So, I completely scrapped that idea and started anew.

Secondly, I discovered that my original gimbal setup was flawed, because while the gimbal itself was at its zero position, I had set the camera and targets to be offset from that position, so the orbiting was all wrong, and felt nasty, and thus the camera was clipping in odd values, causing it to sometimes jump all over the place.

Thirdly, I scrapped the idea of using raycast to calculate distances to determine if the camera should clip through an object or not, and replaced it with an Area that uses a sphere collision shape, which will notify the camera that there is an object close enough to the camera and clip!

And finally, I use another Area with a tall box shape on it to determine if the player has gone under any geometry, and to clip if that is indeed the case. No complicated math needed!

Here's a video of the latest results, by far the smoothest the've been!

Now all I have to do is add mouse/keyboard support, and maybe I can let other people download it and test it out! :p

3 months later

Life got really crazy for a while (having a baby will do that), but I have not stopped this project.

I got distracted by developing some other features for a future demo project, which will show the camera in action, so I added in the following:

  • Moving and/or rotating platform support (by parenting the player to said platforms)
  • Proper joystick deadzone support
  • "Walking on ice" effect, which was just silly and nothing more than an experiment
  • Interactions with rigidbody components (again, just an experiment)

And for features for the actual camera system, I have changed up a ton of the code and done tons of cleaning to better enhance the overall feel of the camera, and while it doesn't look too different from when it did in October, there has been tons of changes to better improve the workflow.

I still need to add proper mouse/keyboard support, and I need to figure out a better way to handle confined spaces - currently I took that feature out until I can get it working better.

Here is a video :

15 days later

Two weeks later and I have made some pretty good progress!

  • Finally added mouse/keyboard support (demonstrated in the first half of the video below)
  • Redesigned the test world
  • Refined how confined spaces work (still may need to tweak a few things)
  • Created ranges for the values assignable in Inspector tab to prevent assigning an absurd value for things like FOV, margins, etc.,
  • Made my repo public!

First, the video!

And finally, here's the repo - please note that you MUST use 3.2 stable if you plan to download/clone this repo to test it out, and hopefully you can make heads and tails of my code... I do plan to document the crap out of the this to make it easier to understand, and I plan to comment/condense the code so that it is much easier to understand, but I've been eager to let other people try this out first, so let me know what you think!

ADDITIONALLY: Please use a gamepad if you have one! Currently, you can switch between mouse mode and gamepad mode by either left-clicking the mouse in-game, or hitting the Escape key in game. Use ALT+F4 to quit the game since I took away the ability to with the Escape key.

This is a direct link to the camera controller script - as you can see it's quite messy, and in fact, I can see many things that aren't doing anything anymore, so I'll tidy that up in the next commit or two, but please be patient as I have a baby and this is very much a "when I get around to it" project. No pull requests please! :p

this looks really awesome. I spent about 3 full days making a non-gimbal locking "freelook" camera, and shudder at trying to get it working as a 3rd person camera.

I think I'll give yours a go instead :)

Thanks for the comments everybody! It's been a long time developing this, and it's nice to know that people are finding this interesting!

I do have an announcement that sounds bad, but is actually good - I have to start the project over!

Basically, I've encountered an issue with mouse control that just couldn't seem to be solved - if the mouse was not moving at a consistent speed, it was possible for the camera to clip through geometry for a brief moment and then catch up after a frame or two, resulting in a horrible "glitchy" feeling and look.

Of course, I didn't discover this until after I published my repo , and I have spent the last week attempting to fix it to no avail whatsoever. Even if I set up a ridiculously high offset value for the clipping distance, it would still happen.

Then I thought to myself, just tonight, "what happens if I get rid of my "View Camera", and just go with the ClippedCamera again?"

And...! That seems to have solved the issue altogether.

I did start developing this project in 3.2 "alpha 0", so it only makes sense that a lot of things may have changed since then, as I no longer seem to need to use a secondary camera at all, and can just rely on the ClippedCamera itself.

I'll have to come up with another way to determine ignoring distance, as well - it seems using a probe with areas for detecting when a body was in the way of the camera also could have been to blame as well, but either way, I like the idea of simplifying this by reducing the amount of cameras needed back down to one.

I'll work on it this weekend and push a commit with the changes by Sunday night, if I can manage it. It shouldn't take too long to make any of the changes, I just have work tomorrow so will have to primarily work on this Sunday morning.

Ok, so... I'm still having issues with the ClippedCamera being able to clip through geometry in certain instances, after all. I'm not sure why my preliminary tests didn't reveal the problems the other night, but when I reworked my script and scene to only use the ClippedCamera, the same exact issues re-appeared, albeit in slightly different ways.

Thus, I believe there are still some internal bugs in ClippedCamera that need ironed out (can anyone verify if the margin property in ClippedCamera actually does anything? It still doesn't seem to affect collision distance like I thought it should, according to its own description).

So, before I lose all of my hair, I'm putting this project on halt until I can maybe find a different solution. It may just be that ClippedCamera doesn't expect to be manipulated like I'm manipulating it, which could be causing my problems, but I suspect it's an internal issue of ClippedCamera itself.

I hope you are able to figure it out without going crazy. I just spent the last few days obsessing over making a wireframe render... so I know what it feels like when things are not perfect :)

a year later

Over a year later....

I've not done much else with the original project. In fact, it currently lays dormant on my github page.

However, I have started doing some experiments with other ideas I have gotten over these past several months. I have not had much time (raising a baby, dealing with other things (like finding out we're expecting a second child!), eating, sleeping...), but some of my preliminary tests are very encouraging!

Since I started and then abandoned this project, some very neat things have been added into Godot, namely the Spring Arm node, and the ability to set the collision shape of the spring arm node! By adjusting the collision shape, it's finally possible to do a "sphere cast", which, in my tests, provides a much more professional and smooth-feeling camera system.

I am still having that issue where the camera will occasionally clip through geometry when it's both moving very fast, and the distance between the camera and the player is greater than maybe 8 or so units. This tells me that the clipping issue could potentially be solved by ensuring the camera cannot reach the floor once it's at a certain distance, and wouldn't be noticed by the player since it would immediately respond to hitting the ground anyway. That's honestly probably how it's handled in most games anyway!

So here are my plans for this going forward.

  1. Completely redo the original project.
  2. Create a reusable scene that anyone can download and instance into their projects.
  3. Provide tons of options, such as choosing how the camera responds to collisions, lerp speed, whether or not you want it to lerp at all, basically everything you can think of will be an option.
  4. Obviously this will be open-sourced!
  5. Model the whole system off of Rockstar's insanely good cameras. This gives me an excuse to play games like RDR2 and GTA V all over again. It's not stealing, it's inspiration! :tongue:

I've been learning a lot over these last few months, and though I've barely been active and have maybe done three hours worth of coding in the last eighteen or so months, I'm confident enough with these tests to try to get this back up and running, and make it even easier for everyone to have a nice camera for their game!

That's a very interesting discussion! I'm glad to see that reduz himself is attempting to tackle this issue as well. Cameras, in my opinion, are what can really make or break a game. This a problem, though, because if the camera in a game is well-coded and behaves naturally, you'll never notice it! Whereas if the camera is poorly done and glitchy, the player will immediately notice and be frustrated by it.

If Godot can have a built-in way of handling a camera setup and give the user an easy way to make a professional feeling camera, that would just be tops.

That said, I still plan to open-source my project (tentatively called "BetterCam", because I suck at coming up with names), and in fact, if anyone wants to look at/follow it, I did start a repo for it the other day. Suggestions/ideas are welcome! It's not functional yet, I've just been setting up the basics whenever I have a free moment.