[Release] Custom character controller

Well, try copying how meguy1 did it with Gravity Shift.

3 Likes

Mygame43 “cheated” with Gravity Shift in that the “down” lookVector always points toward gravity. So no real change to the camera code.

2 Likes

I’d rather have whatever’s possible that can be done, so I can actually use a dynamic camera for my game.

2 Likes

If you just want to be able to look in all 360 degrees, try setting the downVector to always be 90 degrees below the lookVector. It’s an ugly fix but it will absolutely prevent the camera from stopping when it hits the bottom or top of the possible camera angles.

You should quickly realize why the camera is limited like it is currently, when you do.

7 Likes

And just how would I go about doing that?

2 Likes

This topic should get you started in advanced CFrame math. I’m not willing to dive into the scripting it would take to create a 360DOF camera, especially not for free; there are lots of professionally made games which use such technology.

4 Likes

Roblox could implement quaternions under the hood. It would make animating joints probably way easier.

1 Like

Is that me?

8 Likes

Yessiree!

3 Likes

fascinating!!!

2 Likes

Wait, just a question.

Is there any way it’d be possible to have this same effect, but on terrain ? If there is, please let me know!

2 Likes

Unfortunately with the way I approached the problem terrain isn’t really a possibility.

In most cases I can change the fake humanoid’s fake world to rotate around the player, but with terrain that’s not possible since you can’t rotate it. I can’t make a “fake” terrain out of bricks either because not only would that be inefficient but also we don’t have access to that information atm.

3 Likes

Mind explaining how it works?

I am looking forward to using stuff like this!

I have made a working, turning camera for this character controller!

The way it works is, I played with the options of AlignOrientation instances, and noticed their new AlignType property. I played around with this a bit, and found a way to let the Y axis spin freely but keep the X and Z axis relative to the character, using Enum.AlignType.Parallel. After this, I just made sure the part did not rotate too much by setting it’s RotVelocity to 0,0,0 every heartbeat and turning on RigidityEnabled, which is not exactly efficient, and the part rotates minimally, but it works.

I have been playing around with different types of control manipulation for a ControlScript, but all of the methods I have tried simply don’t play nice with the angles. I think it just has something to do with how the humanoid interprets the Humanoid:Move method, since it obviously wouldn’t be walking on ceilings and stuff in any normal Roblox game.

This is the .rbxl file with the modified camera changes. Feel free to explore and test the camera, or modify the custom-made CameraScript if you want.

playgroundCamera.rbxl (91.6 KB)

Since I haven’t figured out how to do the controls, moving around can get pretty wonky. I guess, be careful? :rofl:

Hopefully, this gives the creator of this character controller some out-of-the-box solutions for the next camera or control script he/she implements!

19 Likes

So I reworked my CameraScript to integrate the character controller instead of using an independent part with AlignPosition and AlignOrientation. This required some modifying of the controller’s script to hold a little extra information and place some of its data in some ObjectValues, namely the lastHit and fakeLastHit values. I made sure to stay organized by commenting the modifications starting in pkg and ending with an identifier.

pkg LastPart

I created a relationship between one part’s cframe in fakeWorld and the other one in the real workspace using this formula:

(part.CFrame - part.Position) * (fakePart.CFrame - fakePart.Position):Inverse()

and I used this as the root angle for the camera. Usually, the lastHit part and its fake counterpart is used, and it falls back to the HumanoidRootPart if the lastHit part doesn’t exist. This is kept track of using ObjectValues parented to the controller.

I figured out the ControlScript as well, so have fun moving freely between platforms and not getting frustrated because you’re at some weird angle.

I listed some pros and cons compared to the file in my last post:

Pros:

  • The camera now rotates with parts you are standing on that are spinning on their Y-axis
  • The controls synchronize perfectly with the camera’s movement, which means no more frustration with moving on spinning platforms.
  • No extra part / aligning overhead, if that matters at all

Cons/New Bugs:

  • the camera now spins by 180 degrees whenever you switch between a slope pointing towards the X axis and one pointing towards the Z axis and vice versa, but only while upside-down.
    – This was what my last implementation was able to fix, by being independent from the character controllers.
  • This causes the camera to spin on meshes while upside-down as well.
  • There is still a camera spin whenever there is a transition between an object staying still and an object spinning on its Y-axis, I think I only saw this while standing upside-down as well.

pkg CameraOffset (doesn’t work, addressing a bug)

I haven’t figured out a fix to this upside-down spin bug, but it will probably have to deal with more CFrame manipulation. I will have to understand how to detect when this spin happens though. I almost solved it inside the controller itself (with this package), but it only corrects itself when the character is completely upside-down.

Here is the playground file with the updated ControlScript:

playgroundCamera.rbxl (361.0 KB)

I have added a few keybinds for convenience, that being Tab for resetting movement and Left Ctrl for flipping gravity, which is a really fun feature by itself.
I also added just a few extra obstacles here and there to test out stuff, like stairs.

12 Likes

the long awaited for…

pkg CameraOffset

So I have fixed this upside-down bug, very proud of myself for this one. Mainly because I now know how to use cross product and dot product better. What I did was:

  • I looked in the method for controller.setPart, as that is the relevant method
  • I took the math.atan2 between the X and Z coordinates of private.lastAxis,
  • did the same for the current cross product,
  • took the difference,
  • made sure that the change in angle was never greater than pi.
  • fired an event with this number as the parameter
  • CameraScript’s x value changed accordingly
  • I also copied this over to an extraRotation variable so that the humanoid’s movement did not need to catch up with the camera

Whenever the event fired, the value passed in is added to the x value in the CameraScript, and it makes transitions between slopes nearly seamless.

pkg rPartRot

I have also partially fixed the camera spin bug from rotating parts. It is dependent on the LookVector of the rPart, which means it would be hard to orient these parts correctly if they are asymmetrical, or if the part spins on it’s LookVector. This platform is an example:

Other than this, pkg rPartRot also works when transitioning between two sets of rotating parts at the same time. This could be useful for obbies if you make the gravity independent of the rotating part when you jump through the setNormal method.

My method of implementation for this was limited: it uses very similar functions as the code for pkg CameraOffset. Expansion on this will be next on my to-do list.

Keep in mind that the trigger for this function is dependent on the fact that every rotating part is named “rPart,” just like the autoRotate function that called it.

Controller Comments:

I annotated the controller quite a bit if you didn’t know how it works, albeit you probably still won’t know when you’ve read over it for 20 minutes straight. So, I’ll give the rundown of what happens in the playground file:

  1. The controller is instantiated with the character as the parameter.
  • A fake, or phys,version of the character is created, which controls the physics of the real one. This is known as the physCharacter in the script.

– The physics are manipulated through an AlignOrientation and AlignPosition object, called forces in the script, and the real character’s humanoid is placed in the PlatformStand state.

  • A fake version of the world is also created at WorldCenter, which defaults to 5000 studs away in the X direction. This is the internal physics engine that determines the orientation of your character in the real world.
  1. Every frame, or when autoRotate is called:
  • getFilter is called

– The controller gathers every object in the workspace.World folder that intersects with a 10 stud length Region3 placed at the center of the character’s HumanoidRootPart. This collection of objects is known as a filter in the script.

  • castFeet is called.

– This method casts a cylinder of rays below the character’s feet onto this filter. These rays expose information about the land the character is directly standing on, such as normals, whether it’s complex geometry, etc.

  1. Based on the info gathered from castFeet:
  • If there is a new part, setPart is called.

– This is the method that sets the cframe of your character relative to the world, and the “cframe of the world” relative to your physCharacter in the fakeWorld.

  • updateFakeWorld and updateCharacter are unconditionally called.

updateFakeWorld makes sure to acknowledge any parts that were picked up by the filter, and places any new ones in the fakeWorld, and destroying any old ones.

  • updateCharacter is called

– This sets the Attachment1 property’s CFrame of the AlignPosition and AlignOrientation that is applied to your character. It also makes the physCharacter move in the same direction you are moving

Hopefully, this betters your understanding of what the controller does, along with the existing comments.

Here is the normal file:

playgroundCamera.rbxl (96.4 KB)

This is the debug file:

playgroundCamera.rbxl (106.2 KB)

I don’t understand how these files are different sizes… all I did was change two variables and move the spawn location…

Since it is now possible to walk on spheres and other nice things with good camera and character stability, it might be a cool idea to create some kind of game with planetary gravity mechanics.

30 Likes

Holy smokes dude this is absolutely amazing! I really appreciate that you put the time into making this all the better. Mad respect!

10 Likes

Thanks for the praise!
Honestly, I can see something big coming from this character controller if it gets optimized enough. It could be some big game in the future, or maybe it could inspire something in the Roblox development pipeline.
Even more honestly, it’s all thanks to you for creating this. I have never seen something like this ever on Roblox, and I just want to see someone use it in their game.

Speaking of, I realized I posted that playgroundCamera file in a sort of debug state. I was bit too excited… I will update the post to have that fixed, I guess along with the debug version if anyone is curious, like right now.

4 Likes

Hello! Wanted to ask about the possibility of making a Pathfinders off it. What I mean is that the play can be followed by a mob on a sphere and such.