using Prism; namespace FPSExample { public class FPSPlayer : Entity { public float WalkingSpeed = 10.0f; public float RunSpeed = 20.0f; public float JumpForce = 50.0f; [NonSerialized] public float MouseSensitivity = 10.0f; public float CameraForwardOffset = 0.5f; public float CameraYOffset = 0.5f; private bool m_Colliding = false; private float m_CurrentSpeed; private RigidBodyComponent m_RigidBody; private TransformComponent m_Transform; private TransformComponent m_CameraTransform; private Entity m_CameraEntity; private Vec2 m_LastMousePosition; private float m_CurrentYMovement = 0.0f; private Vec2 m_MovementDirection = new Vec2(0.0f); private bool m_ShouldJump = false; void OnCreate() { m_Transform = GetComponent(); m_RigidBody = GetComponent(); m_CurrentSpeed = WalkingSpeed; AddCollisionBeginCallback((n) => { m_Colliding = true; }); AddCollisionEndCallback((n) => { m_Colliding = false; }); m_CameraEntity = FindEntityByTag("Camera"); m_CameraTransform = m_CameraEntity.GetComponent(); m_LastMousePosition = Input.GetMousePosition(); Input.SetCursorMode(Input.CursorMode.Locked); } void OnUpdate(float ts) { if (Input.IsKeyPressed(KeyCode.Escape) && Input.GetCursorMode() == Input.CursorMode.Locked) Input.SetCursorMode(Input.CursorMode.Normal); if(Input.IsMouseButtonPressed(Input.MouseButton.Left) && Input.GetCursorMode() == Input.CursorMode.Normal) Input.SetCursorMode(Input.CursorMode.Locked); m_CurrentSpeed = Input.IsKeyPressed(KeyCode.LeftControl) ? RunSpeed : WalkingSpeed; UpdateRayCasting(); UpdateMovementInput(); UpdateRotation(ts); UpdateCameraTransform(); } private void UpdateRotation(float ts) { Vec2 currentMousePosition = Input.GetMousePosition(); Vec2 delta = m_LastMousePosition - currentMousePosition; float m_CurrentYMovement = delta.X * MouseSensitivity * ts; float xRotation = delta.Y * MouseSensitivity * ts; m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f)); if (delta.X != 0 || delta.Y != 0) { m_CameraTransform.Rotation += new Vec3(xRotation, m_CurrentYMovement, 0.0f); } m_CameraTransform.Rotation = new Vec3(Mathf.Clamp(m_CameraTransform.Rotation.X, -89.0f, 89.0f), m_CameraTransform.Rotation.YZ); m_LastMousePosition = currentMousePosition; } private void UpdateMovementInput() { if (Input.IsKeyPressed(KeyCode.W)) m_MovementDirection.Y += 1.0f; else if (Input.IsKeyPressed(KeyCode.S)) m_MovementDirection.Y -= 1.0f; else m_MovementDirection.Y = 0.0f; if(Input.IsKeyPressed(KeyCode.A)) m_MovementDirection.X -= 1.0f; else if (Input.IsKeyPressed(KeyCode.D)) m_MovementDirection.X += 1.0f; else m_MovementDirection.X = 0.0f; m_ShouldJump = Input.IsKeyPressed(KeyCode.Space) && !m_ShouldJump; } Collider[] colliders = new Collider[10]; private void UpdateRayCasting() { RaycastHit hitInfo; if (Input.IsKeyPressed(KeyCode.H) && Physics.Raycast(m_CameraTransform.Translation + (m_CameraTransform.Transform.Forward), m_CameraTransform.Transform.Forward, 20.0f, out hitInfo)) { FindEntityByID(hitInfo.EntityID).GetComponent().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f)); } if (Input.IsKeyPressed(KeyCode.I)) { // NOTE: The NonAlloc version of Overlap functions should be used when possible since it doesn't allocate a new array // whenever you call it. The normal versions allocates a brand new array every time. int numColliders = Physics.OverlapBoxNonAlloc(m_Transform.Translation, new Vec3(1.0f), colliders); Console.WriteLine("Colliders: {0}", numColliders); // When using NonAlloc it's not safe to use a foreach loop since some of the colliders may not exist for (int i = 0; i < numColliders; i++) { Console.WriteLine(colliders[i]); } } } void OnPhysicsUpdate(float fixedTimeStep) { UpdateMovement(); } private void UpdateMovement() { m_RigidBody.Rotate(new Vec3(0.0f, m_CurrentYMovement, 0.0f)); Vec3 movement = m_CameraTransform.Transform.Right * m_MovementDirection.X + m_CameraTransform.Transform.Forward * m_MovementDirection.Y; if (m_MovementDirection.LengthSquared() != 0.0f) { movement.Normalize(); Vec3 velocity = movement * m_CurrentSpeed; velocity.Y = m_RigidBody.GetLinearVelocity().Y; m_RigidBody.SetLinearVelocity(velocity); } if (m_ShouldJump && m_Colliding) { m_RigidBody.AddForce(Vec3.Up * JumpForce, RigidBodyComponent.ForceMode.Impulse); m_ShouldJump = false; } } private void UpdateCameraTransform(){ Vec3 position = m_Transform.Translation + m_CameraTransform.Transform.Forward * CameraForwardOffset; position.Y += m_Transform.Translation.Y + CameraYOffset; m_CameraTransform.Translation = position; } } }