I successfully ported the code from my own controller, except its rotation part… Any advice on how to port this part of the code for use with the Kinematic Character Controller?
if (!Input.GetMouseButton(1))
transform.Rotate(0, Input.GetAxisRaw("Horizontal") * characterRotationSpeed * Time.deltaTime, 0);
else if (cameraController.targetCharacterExist)
transform.Rotate(0, Input.GetAxisRaw("Mouse X") * cameraController.sensitivity * cameraController.rotationAcceleration, 0);
To do an equivalent of the Rotate method, you can use quaternion multiplications. Multiplying a quaternion A by a quaternion B makes A rotate locally by B’s rotation, so all you’d have to do is create a quaternion that represents your input rotation, and in UpdateRotation you multiply your currentRotation by that
It should give you something like this:
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
{
float rotationAngleFromInput = 0; // Your input code would set this value from anywhere you want
// Rotates the character around its local Y axis by that angle
currentRotation = currentRotation * Quaternion.Euler(0, rotationAngleFromInput, 0);
}
Hey Phil, I’m getting a weird issue when I connect a PS4 controller to Unity to control the character.
The Move controls on the left analog stick are working perfectly, but the “Look” controls with the right stick drift in weird directions even when I’m not touching the right stick at all.
I dont think it’s an issue with the PS4 controller because I’ve tried it with multiple controllers… The mouse seems to work fine for looking though… Do you know how I could fix it to work with both the mouse and analog stick?
On the bright side: the movement works great with a PS4 controller!
Inputs are handled in ExamplePlayer.cs, and the code that’s there by default is very rudimentary:
Not sure what causes that behaviour with PS4 controller, but by default, it’s just supposed to work with keyboard + mouse. There are so many different ways that one might want to handle input, and so many 3rd party solutions, that I decided to lend that responsibility to the users.
If you want to change it, you just have to build the “_lookInputVector” differently. This is a Vector3 where X represents horizontal look input, and Y represents vertical look input
Yeah I figure it is probably happening because the input axis for a mouse will give float values relative to the screen while a game controller’s joystick will always snap back to Input.GetAxisRaw(“Mouse Y”) = 0 and Input.GetAxisRaw(“Mouse X”) = 0. So as soon as I touch the right analog stick on a controller, it is gathering the mouseLookAxisUp and MouseLookAxis right values of the mouse position on screen and adding those values to the values from the joystick. So if my mouse cursor was perfectly aligned in the middle of the screen, I predict there will be no drifting on the look direction…
Not sure how I’d remedy this but I might try a third party plugin like InControl… Hopefully it will negate any mouse input while using a PS4 controller and vice versa
I don’t get smooth movement, stutters do show up. I setup a very simple scene (Unity cubes) and a constant velocity to move past them. I have a parent container that holds the VR camera. On the parent I added KinematicCharacterMotor, leaving everything at the defaults and I add my character controller to it, which has:
Your UpdateVelocity code is fine, and it couldn’t be a problem either way. I arranged things so that no matter what you return as the “currentVelocity”, the movement of the character will always be properly interpolated
This problem’s gotta have something to do with the way VR makes the camera move, and the fact that it probably doesn’t like having a rigidbody attached to that camera. What’s probably happening is that VR sets the camera’s position/rotation directly, and this messes with your camera rigidbody’s interpolation. The fact that you end up with a rigidbody within another rigidbody is also very suspicious (it’s been known to cause all kinds of problems). Here’s a few thoughts on this:
In Edit > Project Settings > Time, set the Fixed Timestep to 0.3. Now try playing your example scene.
Do you see your camera moving like a slideshow (does it update only about 3 times per second)?
And if you look at your character object in the scene view, is it still moving smoothly?
To avoid problems like these, I personally wouldn’t use a rigidbody to handle collisions on the VR camera. Instead, I’d attach a script to the camera that does a Physics.OverlapSphereNonAlloc(), and then a Physics.ComputePenetration() to solve collisions manually. And all this would happen in LateUpdate(). Not only would this make your collision handling frame-perfect, but it’s also likely to solve this jitteriness problem. Look at the example code here if you’re not sure how this works
The camera does not have a rigidbody, and there is only one rigidbody.
CameraParent (with rb and movement script) > Camera (child)
Results with 0.3 Fixed Timestep:
Note: When I reduced the Timestep, the rigidbody went very fast, until I reduced the speed multiplier. That means the velocity is affected by the Timestep and is not absolute, so if the Timestep varied a little, would that cause a hitch?
The CameraParent walks along like a slideshow (Scene view)
The Camera is mostly smooth (Scene view)
VR mostly smooth, some stutters as originally described
Does the above give you any other ideas?
I will look into your last recommendation. Thanks.
Hey Phil- quick question about the character controller… Is there an easy way to make it fly/hover?
Say- when holding the space bar the character will float upwards instead of jump?
I know theres a noClip state but thats not quite what I’m looking for. Thanks man!
Edit: Actually I think I might be on track towards figuring it out… Will post here once I’ve got a solution
Edit: OK I got it. Posting here for anyone else that wants to use flight in their character:
Phil has done a really great job of making this super simple. Open MyPlayer or ExamplePlayer script (whichever youre using) and go to the Jump section:
Right now it should say something like:
if (Input.GetButtonDown (“Jump”)) { Character.Jump (); }
Just change it to:
if (Input.GetButton (“Jump”)) {
Character.GetComponent().ForceUnground ();
Character.AddVelocity (Vector3.up * .6f);
}
You have to force unground for obvious reasons mentioned in the walkthrough- alternatively, if you want your character to launch off like a superhero or Overwatch character (COUGHPharahCOUGH) you can do this:
Oh wait, I was actually totally wrong in the other post when I said the velocity code wasn’t a problem. I didn’t notice the “* deltaTime”. Unlike direct movements, velocities are independant of framerates, so they must not be multiplied by the deltaTime. This is what’s causing your problem of the velocity being different depending on the fixedTimeStep.
So if the CameraParent (aka the KinematicCharacterMotor) is a slideshow, this is not normal. The first thing we need to establish is if the VR camera setup has anything to do with that problem. Try fixing the velocity as described above, putting the fixedTimeStep back to 0.3, and running the default CharacterPlayground scene that comes with the package.
If you still see the character moving like a slideshow under these conditions, that means something in the core scripts may have been altered
In the jump handling part of ExampleCharacterController’s UpdateVelocity(), there’s this code:
I think what you want is to remove the whole " - Vector3.Project(…)" part, which tries to cancel-out slope velocity when jumping. If not, I might need some more clarifications
Makes sense about the velocity, and it is consistent now. Since you supply deltaTime in the call I assumed it was suppose to be used.
I was wrong about the CameraParent slideshowing. When it is selected in the Hierarchy, the transform gizmo in the scene view does step every 1/3 of a second, but the actual object is smooth. So, it is smooth as viewed from Scene view.
Now I am getting mostly smooth results. Instead of regular jitter, a few really big hitches, so I did a build with the profiler and I am having no hitches right now. I will keep testing.
Edit: I just rebuilt scene without devel/profile and it has big hitches, occurring every 3 to 20 seconds. I then built with profiler on and no hitches. Strange.
Edit2: A development build (with or without profiling) = no hitches, non-devel build = hitches.
Edit3: Ah, I the timestep was still at 0.3 on the above hitches. I switched it to 0.01111 and the big hitches are gone, but the occasional consistent jitters are back. This is in a deployment build.
@flyingaudio
Do you think it’s possible that the jitter you’re still experiencing might look like this bug ?
Rigidbody intrepolation has some problems in Unity 2017.2 and .3, and it seems to depend a lot on the platforms/contexts. Sometimes it happens, sometimes it doesn’t. However, [mention|qztipHnpd7HujWyTg2eYuQ==] mentioned here that this might get fixed at some point in 2018.1 when PhysX3.4 arrives
I’d suggest making some very simple tests, like replacing the character controller with an extremely simple interpolated kinematic rigidbody that moves with your input, and see if you still get jitter with that same camera setup. You could also try your current setup in 2017.1 to see if that solves the problem
So I just tried the above test in 2017.3.0f2. I started a completely new project, added an interpolated kinematic rigidbody cube to a scene, added a regular non-VR camera as a child, and started moving around with a simple script. And I do get jitters every 1 second or so in a build - but not in editor. This very clearly seems like an engine bug to me
Here’s the code I used to move my rigidbody around:
This would be something you’d have to implement yourself, but it’d be quite simple. Here’s an overview of what you’d have to do:
When you press a certain button, or when you detect a collision with another character (depends on how you want to trigger attaching to characters)…
Call an already-existing method on the jumping character controller that deactivates its movement/physics logic
Either make your character a child of the other, or write some code on Update() that acts like a parent constraint and makes the character follow the other without having to use actual parenting