Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
FPSControl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
unity
FPSControl
Commits
223f6ec9
Commit
223f6ec9
authored
5 years ago
by
David Huss
Browse files
Options
Downloads
Patches
Plain Diff
Add FPSController.cs
parent
4ce04470
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
FPSController.cs
+215
-0
215 additions, 0 deletions
FPSController.cs
with
215 additions
and
0 deletions
FPSController.cs
0 → 100644
+
215
−
0
View file @
223f6ec9
using
System.Collections
;
using
System.Collections.Generic
;
using
UnityEngine
;
// Generic First-Person-Shooter-like Controller
[
RequireComponent
(
typeof
(
CharacterController
))]
public
class
FPSController
:
MonoBehaviour
{
[
Tooltip
(
"How fast the player moves when walking (default move speed)."
)]
[
SerializeField
]
private
float
movementWalkSpeed
=
6.0f
;
[
Tooltip
(
"How fast the player moves when running."
)]
[
SerializeField
]
private
float
movementRunSpeed
=
11.0f
;
[
Tooltip
(
"If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster."
)]
[
SerializeField
]
public
bool
movementLimitDiagonalSpeed
=
true
;
[
Tooltip
(
"If checked, the run key toggles between running and walking. Otherwise player runs if the key is held down."
)]
[
SerializeField
]
private
bool
movementToggleRun
=
false
;
[
Tooltip
(
"How high the player jumps when hitting the jump button."
)]
[
SerializeField
]
private
float
movementJumpSpeed
=
8.0f
;
[
Tooltip
(
"How fast the player falls when not standing on anything."
)]
[
SerializeField
]
private
float
movementGravity
=
20.0f
;
[
Tooltip
(
"Units that player can fall before a falling function is run. To disable, type \"infinity\" in the inspector."
)]
[
SerializeField
]
private
float
movementFallingThreshold
=
10.0f
;
[
Tooltip
(
"If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down."
)]
[
SerializeField
]
private
bool
movementSlideWhenOverSlopeLimit
=
false
;
[
Tooltip
(
"If checked and the player is on an object tagged \"Slide\", he will slide down it regardless of the slope limit."
)]
[
SerializeField
]
private
bool
movementSlideOnTaggedObjects
=
false
;
[
Tooltip
(
"How fast the player slides when on slopes as defined above."
)]
[
SerializeField
]
private
float
movementSlideSpeed
=
12.0f
;
[
Tooltip
(
"If checked, then the player can change direction while in the air."
)]
[
SerializeField
]
private
bool
movementAirControl
=
false
;
[
Tooltip
(
"Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast."
)]
[
SerializeField
]
private
float
movementAntiBumpFactor
=
.
75f
;
[
Tooltip
(
"Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping."
)]
[
SerializeField
]
private
int
movementAntiBunnyHopFactor
=
1
;
private
Vector3
movementMoveDirection
=
Vector3
.
zero
;
private
bool
movementGrounded
=
false
;
private
CharacterController
movementController
;
private
Transform
movementTransform
;
private
float
movementSpeed
;
private
RaycastHit
movementHit
;
private
float
movementFallStartLevel
;
private
bool
movementFalling
;
private
float
movementSlideLimit
;
private
float
movementRayDistance
;
private
Vector3
movementContactPoint
;
private
bool
movementPlayerControl
=
false
;
private
int
movementJumpTimer
;
private
void
Start
()
{
// Saving component references to improve performance.
movementTransform
=
GetComponent
<
Transform
>();
movementController
=
GetComponent
<
CharacterController
>();
// Setting initial values.
movementSpeed
=
movementWalkSpeed
;
movementRayDistance
=
movementController
.
height
*
.
5f
+
movementController
.
radius
;
movementSlideLimit
=
movementController
.
slopeLimit
-
.
1f
;
movementJumpTimer
=
movementAntiBunnyHopFactor
;
}
private
void
Update
()
{
// If the run button is set to toggle, then switch between walk/run speed. (We use Update for this...
// FixedUpdate is a poor place to use GetButtonDown, since it doesn't necessarily run every frame and can miss the event)
if
(
movementToggleRun
&&
movementGrounded
&&
Input
.
GetButtonDown
(
"Run"
))
{
movementSpeed
=
(
movementSpeed
==
movementWalkSpeed
?
movementRunSpeed
:
movementWalkSpeed
);
}
}
private
void
FixedUpdate
()
{
float
inputX
=
Input
.
GetAxis
(
"Horizontal"
);
float
inputY
=
Input
.
GetAxis
(
"Vertical"
);
// If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed
float
inputModifyFactor
=
(
inputX
!=
0.0f
&&
inputY
!=
0.0f
&&
movementLimitDiagonalSpeed
)
?
.
7071f
:
1.0f
;
if
(
movementGrounded
)
{
bool
sliding
=
false
;
// See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
// because that interferes with step climbing amongst other annoyances
if
(
Physics
.
Raycast
(
movementTransform
.
position
,
-
Vector3
.
up
,
out
movementHit
,
movementRayDistance
))
{
if
(
Vector3
.
Angle
(
movementHit
.
normal
,
Vector3
.
up
)
>
movementSlideLimit
)
{
sliding
=
true
;
}
}
// However, just raycasting straight down from the center can fail when on steep slopes
// So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
else
{
Physics
.
Raycast
(
movementContactPoint
+
Vector3
.
up
,
-
Vector3
.
up
,
out
movementHit
);
if
(
Vector3
.
Angle
(
movementHit
.
normal
,
Vector3
.
up
)
>
movementSlideLimit
)
{
sliding
=
true
;
}
}
// If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
if
(
movementFalling
)
{
movementFalling
=
false
;
if
(
movementTransform
.
position
.
y
<
movementFallStartLevel
-
movementFallingThreshold
)
{
OnFell
(
movementFallStartLevel
-
movementTransform
.
position
.
y
);
}
}
// If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
if
(!
movementToggleRun
)
{
movementSpeed
=
Input
.
GetKey
(
KeyCode
.
LeftShift
)
?
movementRunSpeed
:
movementWalkSpeed
;
}
// If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
if
((
sliding
&&
movementSlideWhenOverSlopeLimit
)
||
(
movementSlideOnTaggedObjects
&&
movementHit
.
collider
.
tag
==
"Slide"
))
{
Vector3
hitNormal
=
movementHit
.
normal
;
movementMoveDirection
=
new
Vector3
(
hitNormal
.
x
,
-
hitNormal
.
y
,
hitNormal
.
z
);
Vector3
.
OrthoNormalize
(
ref
hitNormal
,
ref
movementMoveDirection
);
movementMoveDirection
*=
movementSlideSpeed
;
movementPlayerControl
=
false
;
}
// Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
else
{
movementMoveDirection
=
new
Vector3
(
inputX
*
inputModifyFactor
,
-
movementAntiBumpFactor
,
inputY
*
inputModifyFactor
);
movementMoveDirection
=
movementTransform
.
TransformDirection
(
movementMoveDirection
)
*
movementSpeed
;
movementPlayerControl
=
true
;
}
// Jump! But only if the jump button has been released and player has been grounded for a given number of frames
if
(!
Input
.
GetButton
(
"Jump"
))
{
movementJumpTimer
++;
}
else
if
(
movementJumpTimer
>=
movementAntiBunnyHopFactor
)
{
movementMoveDirection
.
y
=
movementJumpSpeed
;
movementJumpTimer
=
0
;
}
}
else
{
// If we stepped over a cliff or something, set the height at which we started falling
if
(!
movementFalling
)
{
movementFalling
=
true
;
movementFallStartLevel
=
movementTransform
.
position
.
y
;
}
// If air control is allowed, check movement but don't touch the y component
if
(
movementAirControl
&&
movementPlayerControl
)
{
movementMoveDirection
.
x
=
inputX
*
movementSpeed
*
inputModifyFactor
;
movementMoveDirection
.
z
=
inputY
*
movementSpeed
*
inputModifyFactor
;
movementMoveDirection
=
movementTransform
.
TransformDirection
(
movementMoveDirection
);
}
}
// Apply gravity
movementMoveDirection
.
y
-=
movementGravity
*
Time
.
deltaTime
;
// Move the controller, and set grounded true or false depending on whether we're standing on something
movementGrounded
=
(
movementController
.
Move
(
movementMoveDirection
*
Time
.
deltaTime
)
&
CollisionFlags
.
Below
)
!=
0
;
}
// Store point that we're in contact with for use in FixedUpdate if needed
private
void
OnControllerColliderHit
(
ControllerColliderHit
hit
)
{
movementContactPoint
=
hit
.
point
;
}
// This is the place to apply things like fall damage. You can give the player hitpoints and remove some
// of them based on the distance fallen, play sound effects, etc.
private
void
OnFell
(
float
fallDistance
)
{
print
(
"Ouch! Fell "
+
fallDistance
+
" units!"
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment