hi, i was wondering how to make a fps style head look controller. what i currently have allows you to look up and down while walking, if you attempt to look left or right the character (depending on how far you look ) will spin constantly in that direction, faster the the further you look, standing still it works as intended allowing free look. i can’t seem to figure out how to get it to turn to the direction then walk in the direction the character’s head is facing when there is input on the forward / backward axis.
Not entirely sure what you are wanting here. If you just want an FPS controller, use the one from the Standard Assets. (Assets > Import Package > Characters)
the standard assets fps controller is useless for what i need it for, it’s too fixed function. i need one (like mine) that is totally dynamic and reacts to the environment that it is in, feature parkour, adaptive targeting and strategies for ai, and support for multiple gamemodes by calling different classes based on the current game state. i really don’t feel like learning the standard assets script(s) then modifying it.
alright. it will take me a minute to find this, it is burried in a mass of ~ 2k lines of code.
here is what i currently have, the character controller revolves around rigidbodies and i have cut it out of the mass block of code and am currently working on terrain hugging to go with it (which works, im gonna have to combine the output of that with this to make the input of new forced rotation variables). at the moment has no interpolation in the rotate character operation (not worried about that at the moment) the character can be directly rotated by the input of torque from the alternate arrow input axis. i remember reading something about euler angles vaguely stating they were worldspace rotations? if i could somehow override the orientation of the character’s head and have it simulated in worldspace instead of local space that would be great and i could finish up the rest up from there.
// mouselook
void LateUpdate(){
// Ensure the cursor is always locked when set
Screen.lockCursor = lockCursor;
if (Input.GetKeyDown("c")){
if (!lockCursor){
lockCursor = true;
}else if (lockCursor){
lockCursor = false;
}
}
// Allow the script to clamp based on a desired target value.
var targetOrientation = Quaternion.Euler(targetDirection);
var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);
// Get raw mouse input for a cleaner reading on more sensitive mice.
if (lockCursor){
var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
// Scale input against the sensitivity setting and multiply that against the smoothing value.
mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));
// Interpolate mouse movement over time to apply smoothing delta.
smoothMouse.x = Mathf.Lerp(smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
smoothMouse.y = Mathf.Lerp(smoothMouse.y, mouseDelta.y, 1f / smoothing.y);
// Find the absolute mouse movement value from point zero.
mouseAbsolute += smoothMouse;
// Clamp and apply the local x value first, so as not to be affected by world transforms.
if (clampInDegrees.x < 360)
mouseAbsolute.x = Mathf.Clamp(mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);
var xRotation = Quaternion.AngleAxis(-mouseAbsolute.y, targetOrientation * Vector3.right);
head.transform.localRotation = xRotation;
// Then clamp and apply the global y value.
if (clampInDegrees.y < 360)
mouseAbsolute.y = Mathf.Clamp(mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);
head.transform.localRotation *= targetOrientation;
var yRotation = Quaternion.AngleAxis(mouseAbsolute.x, head.transform.InverseTransformDirection(Vector3.up));
head.transform.localRotation *= yRotation;
}
}
void FixedUpdate(){
// a temporary solution to move the characters rigidbody in response to look direction on the y axis
rb.MoveRotation(Quaternion.Euler(transform.eulerAngles.x, head.transform.eulerAngles.y, transform.eulerAngles.z));
}
true, that it does but. it doesn’t have what i need in it and i don’t feel like learning that script then re implementing what i currently have in my rigidbody controller, it vastly outweighs the “standard” unity scripts in features in every way. i did have a look at it and seen that mostly everything in it is done from a blend tree… which means more animations, im at a memory cap and every MB that isn’t used counts.
There are a lot of great simple mouselook examples floating around if you search for them. I like the second one on this answer, it works:
(and more important it’s easy to understand. I can relate to his wish for Unity to have very simple example scripts included- I imagine if you’re more experienced the included stuff is great for rapid prototyping but they’re no good to learn from as a beginner to OOP)
I don’t know how the hell you guys maintain code without whitespaces, each to their own but man is that masochistic in my opinion. I’ve had people give me shit about my code being all stretched out and I’m just like "I mean I am brand new" but to myself I kinda think like “also that’s what MS’ VS suggests by default…”
I mean you can do it, but why worry about the player’s body orientation at all for now? Just move the player based on the camera’s transform.forward / transform.right vectors maybe?
Then let the player’s body either rotate to match that or rotate the players body when you rotate the camera, but only in body’s Y dimension?
Maybe that’s bad separation of concerns / single responsibility principle though. I do think you would benefit from having a camera controller and a player controller that are separate but related… That’ll let you do stuff to them separately later if you want.
thanks for the example, and the link, though i seen that link already but never really looked at it. looking at both, i may have found my issue and will attempt a fix. as for my character controller and my camrig, they are totally separate from one another, the camrig supports up to 4 tracking targets creating a vector between all specified and will always have all the specified targets on the screen and it supports 5 targeting modes: normal, pan, reverse view, 2 objective modes and cinematic. to find a target on multiplayer or singleplayer it searches the current level’s dynamic entity list after it is spawned, on the first spawn of the player it was created with it gets a string that is associated with that player for the session and will track it until the player leaves the match or is destroyed upon returning to the menu, it is then nullified and the camera is destroyed returning the view to the main menu view, which begins rendering again. and the no spaces is a optimization technique, best suited for mobile and web browser as the compiler has less to “examine” in the matter of empty lines or spaces. my character controller used to bog my galaxy s2 lte edition down to about 6 fps, now it has no noticeable impacts and without bloom and sun shafts the game runs on max at 56 fps.