diff --git a/Modified fragsurf/CameraWaterCheck.cs b/Modified fragsurf/CameraWaterCheck.cs new file mode 100644 index 0000000..114e905 --- /dev/null +++ b/Modified fragsurf/CameraWaterCheck.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class CameraWaterCheck : MonoBehaviour { + + private List triggers = new List (); + + private void OnTriggerEnter (Collider other) { + + if (!triggers.Contains (other)) + triggers.Add (other); + + } + + private void OnTriggerExit (Collider other) { + + if (triggers.Contains (other)) + triggers.Remove (other); + + } + + public bool IsUnderwater () { + + foreach (Collider trigger in triggers) { + + if (trigger.GetComponentInParent ()) + return true; + + } + + return false; + + } + +} diff --git a/Modified fragsurf/CameraWaterCheck.cs.meta b/Modified fragsurf/CameraWaterCheck.cs.meta new file mode 100644 index 0000000..357675a --- /dev/null +++ b/Modified fragsurf/CameraWaterCheck.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f1d7457460534f489c8262e748c0dfc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Example player prefab.prefab b/Modified fragsurf/Example player prefab.prefab new file mode 100644 index 0000000..4c0042d --- /dev/null +++ b/Modified fragsurf/Example player prefab.prefab @@ -0,0 +1,227 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &5467285083954485886 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5467285083954485881} + - component: {fileID: 5467285083954485883} + - component: {fileID: 5467285083954485880} + m_Layer: 8 + m_Name: Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5467285083954485881 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285083954485886} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5467285085316221433} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &5467285083954485883 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285083954485886} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 1000 + field of view: 90 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &5467285083954485880 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285083954485886} + m_Enabled: 1 +--- !u!1 &5467285084242854813 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5467285084242854812} + - component: {fileID: 5467285084242854815} + m_Layer: 8 + m_Name: Example player prefab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5467285084242854812 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285084242854813} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5467285085316221433} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5467285084242854815 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285084242854813} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 601d4686cc0b70d45a98271d52094850, type: 3} + m_Name: + m_EditorClassIdentifier: + colliderSize: {x: 1, y: 2, z: 1} + collisionType: 1 + weight: 75 + rigidbodyPushForce: 0.5 + solidCollider: 1 + viewTransform: {fileID: 5467285085316221433} + playerRotationTransform: {fileID: 5467285084242854812} + crouchingHeightMultiplier: 0.5 + crouchingSpeed: 10 + crouchingEnabled: 1 + slidingEnabled: 0 + movementConfig: + autoBhop: 1 + gravity: 20 + jumpForce: 6.5 + friction: 6 + maxSpeed: 6 + maxVelocity: 50 + slopeLimit: 45 + clampAirSpeed: 1 + airCap: 0.4 + airAcceleration: 12 + airFriction: 0.4 + walkSpeed: 7 + sprintSpeed: 12 + acceleration: 14 + deceleration: 10 + crouchSpeed: 4 + crouchAcceleration: 8 + crouchDeceleration: 4 + crouchFriction: 3 + minimumSlideSpeed: 9 + maximumSlideSpeed: 18 + slideSpeedMultiplier: 1.75 + slideFriction: 15 + downhillSlideSpeedMultiplier: 3 + slideDelay: 1 + swimUpSpeed: 12 + underwaterSwimSpeed: 3 + underwaterAcceleration: 6 + underwaterDeceleration: 3 + underwaterFriction: 2 + underwaterGravity: 6 + underwaterVelocityDampening: 2 +--- !u!1 &5467285085316221438 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5467285085316221433} + - component: {fileID: 5467285085316221432} + m_Layer: 8 + m_Name: Camera holder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5467285085316221433 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285085316221438} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5467285083954485881} + m_Father: {fileID: 5467285084242854812} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5467285085316221432 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5467285085316221438} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 604093a680e6d5a488206647cc35be23, type: 3} + m_Name: + m_EditorClassIdentifier: + bodyTransform: {fileID: 5467285084242854812} + sensitivityMultiplier: 1 + horizontalSensitivity: 1 + verticalSensitivity: 1 + minYRotation: -90 + maxYRotation: 90 + bodyRotation: 0 + cameraRotation: {x: 0, y: 0, z: 0} + leanInput: 0 + sway: 0 diff --git a/Modified fragsurf/Example player prefab.prefab.meta b/Modified fragsurf/Example player prefab.prefab.meta new file mode 100644 index 0000000..3f1b1a0 --- /dev/null +++ b/Modified fragsurf/Example player prefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a840589249729984398df665ca6e2508 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Extensions.meta b/Modified fragsurf/Extensions.meta new file mode 100644 index 0000000..84f6453 --- /dev/null +++ b/Modified fragsurf/Extensions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d28ade60e8ecfdf42970424f92cd001e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Extensions/IntExtensions.cs b/Modified fragsurf/Extensions/IntExtensions.cs new file mode 100644 index 0000000..49864c0 --- /dev/null +++ b/Modified fragsurf/Extensions/IntExtensions.cs @@ -0,0 +1,27 @@ + +public static class IntExtensions { + + /// + /// + /// + /// + /// + /// + public static bool HasFlag (this int a, int b) { return (a & b) == b; } + + /// + /// + /// + /// + /// + /// + public static int AddFlag (this int a, int b) { return a |= b; } + + /// + /// + /// + /// + /// + /// + public static int RemoveFlag (this int a, int b) { return a &= ~b; } +} \ No newline at end of file diff --git a/Modified fragsurf/Extensions/IntExtensions.cs.meta b/Modified fragsurf/Extensions/IntExtensions.cs.meta new file mode 100644 index 0000000..a3d3fbf --- /dev/null +++ b/Modified fragsurf/Extensions/IntExtensions.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: dcb5a3ee06e4bc947a5486cd6b06e1ac +timeCreated: 1522007229 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Extensions/VectorExtensions.cs b/Modified fragsurf/Extensions/VectorExtensions.cs new file mode 100644 index 0000000..1134ac3 --- /dev/null +++ b/Modified fragsurf/Extensions/VectorExtensions.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +public static class VectorExtensions { + + public static Vector3 VectorMa (Vector3 start, float scale, Vector3 direction) { + + var dest = new Vector3 ( + start.x + direction.x * scale, + start.y + direction.y * scale, + start.z + direction.z * scale + ); + + return dest; + + } + +} \ No newline at end of file diff --git a/Modified fragsurf/Extensions/VectorExtensions.cs.meta b/Modified fragsurf/Extensions/VectorExtensions.cs.meta new file mode 100644 index 0000000..4bbc3c8 --- /dev/null +++ b/Modified fragsurf/Extensions/VectorExtensions.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 390f54ee3fdd73a46916bef3d176880f +timeCreated: 1522007209 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement.meta b/Modified fragsurf/Movement.meta new file mode 100644 index 0000000..5683039 --- /dev/null +++ b/Modified fragsurf/Movement.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b1e33b474eb4614aa6a5972cd4febbc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/ISurfControllable.cs b/Modified fragsurf/Movement/ISurfControllable.cs new file mode 100644 index 0000000..3d03b14 --- /dev/null +++ b/Modified fragsurf/Movement/ISurfControllable.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace Fragsurf.Movement { + + public interface ISurfControllable { + + MoveType moveType { get; } + MoveData moveData { get; } + Collider collider { get; } + GameObject groundObject { get; set; } + Vector3 forward { get; } + Vector3 right { get; } + Vector3 up { get; } + Vector3 baseVelocity { get; } + + } +} diff --git a/Modified fragsurf/Movement/ISurfControllable.cs.meta b/Modified fragsurf/Movement/ISurfControllable.cs.meta new file mode 100644 index 0000000..ec769e5 --- /dev/null +++ b/Modified fragsurf/Movement/ISurfControllable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce6dfe3283d91574aa798e5855fc14dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/InputButtons.cs b/Modified fragsurf/Movement/InputButtons.cs new file mode 100644 index 0000000..e288dbc --- /dev/null +++ b/Modified fragsurf/Movement/InputButtons.cs @@ -0,0 +1,16 @@ + +namespace Fragsurf.Movement { + + [System.Flags] + public enum InputButtons { + None = 0, + Jump = 1 << 1, + Duck = 1 << 2, + Speed = 1 << 3, + MoveLeft = 1 << 4, + MoveRight = 1 << 5, + MoveForward = 1 << 6, + MoveBack = 1 << 7 + } + +} diff --git a/Modified fragsurf/Movement/InputButtons.cs.meta b/Modified fragsurf/Movement/InputButtons.cs.meta new file mode 100644 index 0000000..1dda9da --- /dev/null +++ b/Modified fragsurf/Movement/InputButtons.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a3ecfdc05e51544ead319fa03e199fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/MoveData.cs b/Modified fragsurf/Movement/MoveData.cs new file mode 100644 index 0000000..2cf833c --- /dev/null +++ b/Modified fragsurf/Movement/MoveData.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace Fragsurf.Movement { + + public enum MoveType { + None, + Walk, + Noclip, // not implemented + Ladder, // not implemented + } + + public class MoveData { + + ///// Fields ///// + + public Transform playerTransform; + public Transform viewTransform; + public Vector3 viewTransformDefaultLocalPos; + + public Vector3 origin; + public Vector3 viewAngles; + public Vector3 velocity; + public float forwardMove; + public float sideMove; + public float upMove; + public float surfaceFriction = 1f; + public float gravityFactor = 1f; + public float walkFactor = 1f; + public float verticalAxis = 0f; + public float horizontalAxis = 0f; + public bool wishJump = false; + public bool crouching = false; + public bool sprinting = false; + + public float rigidbodyPushForce = 1f; + + public float defaultHeight = 2f; + public float crouchingHeight = 1f; + public float crouchingSpeed = 10f; + public bool toggleCrouch = false; + + public bool slidingEnabled = false; + + public bool underwater = false; + public bool cameraUnderwater = false; + + public bool grounded = false; + public bool groundedTemp = false; + public float fallingVelocity = 0f; + + } +} diff --git a/Modified fragsurf/Movement/MoveData.cs.meta b/Modified fragsurf/Movement/MoveData.cs.meta new file mode 100644 index 0000000..3ba9d6a --- /dev/null +++ b/Modified fragsurf/Movement/MoveData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01040416c3a2d664aacf1cdfc7a46675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/MovementConfig.cs b/Modified fragsurf/Movement/MovementConfig.cs new file mode 100644 index 0000000..c0c2a9c --- /dev/null +++ b/Modified fragsurf/Movement/MovementConfig.cs @@ -0,0 +1,55 @@ +using UnityEngine; +namespace Fragsurf.Movement { + + [System.Serializable] + public class MovementConfig { + + [Header ("Jumping and gravity")] + public bool autoBhop = true; + public float gravity = 20f; + public float jumpForce = 6.5f; + + [Header ("General physics")] + public float friction = 6f; + public float maxSpeed = 6f; + public float maxVelocity = 50f; + [Range (30f, 75f)] public float slopeLimit = 45f; + + [Header ("Air movement")] + public bool clampAirSpeed = true; + public float airCap = 0.4f; + public float airAcceleration = 12f; + public float airFriction = 0.4f; + + [Header ("Ground movement")] + public float walkSpeed = 7f; + public float sprintSpeed = 12f; + public float acceleration = 14f; + public float deceleration = 10f; + + [Header ("Crouch movement")] + public float crouchSpeed = 4f; + public float crouchAcceleration = 8f; + public float crouchDeceleration = 4f; + public float crouchFriction = 3f; + + [Header ("Sliding")] + public float minimumSlideSpeed = 9f; + public float maximumSlideSpeed = 18f; + public float slideSpeedMultiplier = 1.75f; + public float slideFriction = 14f; + public float downhillSlideSpeedMultiplier = 2.5f; + public float slideDelay = 0.5f; + + [Header ("Underwater")] + public float swimUpSpeed = 12f; + public float underwaterSwimSpeed = 3f; + public float underwaterAcceleration = 6f; + public float underwaterDeceleration = 3f; + public float underwaterFriction = 2f; + public float underwaterGravity = 6f; + public float underwaterVelocityDampening = 2f; + + } + +} diff --git a/Modified fragsurf/Movement/MovementConfig.cs.meta b/Modified fragsurf/Movement/MovementConfig.cs.meta new file mode 100644 index 0000000..9bc72b2 --- /dev/null +++ b/Modified fragsurf/Movement/MovementConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a624624f32edf641ba5049808071214 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/SurfCharacter.cs b/Modified fragsurf/Movement/SurfCharacter.cs new file mode 100644 index 0000000..8a0afeb --- /dev/null +++ b/Modified fragsurf/Movement/SurfCharacter.cs @@ -0,0 +1,366 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace Fragsurf.Movement { + + /// + /// Easily add a surfable character to the scene + /// + [AddComponentMenu ("Fragsurf/Surf Character")] + public class SurfCharacter : MonoBehaviour, ISurfControllable { + + public enum ColliderType { + Capsule, + Box + } + + ///// Fields ///// + + [Header("Physics Settings")] + public Vector3 colliderSize = new Vector3 (1f, 2f, 1f); + public ColliderType collisionType; + public float weight = 75f; + public float rigidbodyPushForce = 2f; + public bool solidCollider = false; + + [Header("View Settings")] + public Transform viewTransform; + public Transform playerRotationTransform; + + [Header ("Crouching setup")] + public float crouchingHeightMultiplier = 0.5f; + public float crouchingSpeed = 10f; + float defaultHeight; + bool allowCrouch = true; // This is separate because you shouldn't be able to toggle crouching on and off during gameplay for various reasons + + [Header ("Features")] + public bool crouchingEnabled = true; + public bool slidingEnabled = false; + + [Header ("Movement Config")] + [SerializeField] + public MovementConfig movementConfig; + + private GameObject _groundObject; + private Vector3 _baseVelocity; + private Collider _collider; + private Vector3 _angles; + private Vector3 _startPosition; + private GameObject _colliderObject; + private GameObject _cameraWaterCheckObject; + private CameraWaterCheck _cameraWaterCheck; + + private MoveData _moveData = new MoveData (); + private SurfController _controller = new SurfController (); + + private Rigidbody rb; + + private List triggers = new List (); + private int numberOfTriggers = 0; + + private bool underwater = false; + + ///// Properties ///// + + public MoveType moveType { get { return MoveType.Walk; } } + public MovementConfig moveConfig { get { return movementConfig; } } + public MoveData moveData { get { return _moveData; } } + public new Collider collider { get { return _collider; } } + + public GameObject groundObject { + + get { return _groundObject; } + set { _groundObject = value; } + + } + + public Vector3 baseVelocity { get { return _baseVelocity; } } + + public Vector3 forward { get { return viewTransform.forward; } } + public Vector3 right { get { return viewTransform.right; } } + public Vector3 up { get { return viewTransform.up; } } + + Vector3 prevPosition; + + ///// Methods ///// + + private void Awake () { + + _controller.playerTransform = playerRotationTransform; + + if (viewTransform != null) { + + _controller.camera = viewTransform; + _controller.cameraYPos = viewTransform.localPosition.y; + + } + + } + + private void Start () { + + _colliderObject = new GameObject ("PlayerCollider"); + _colliderObject.layer = gameObject.layer; + _colliderObject.transform.SetParent (transform); + _colliderObject.transform.rotation = Quaternion.identity; + _colliderObject.transform.localPosition = Vector3.zero; + _colliderObject.transform.SetSiblingIndex (0); + + // Water check + _cameraWaterCheckObject = new GameObject ("Camera water check"); + _cameraWaterCheckObject.layer = gameObject.layer; + _cameraWaterCheckObject.transform.position = viewTransform.position; + + SphereCollider _cameraWaterCheckSphere = _cameraWaterCheckObject.AddComponent (); + _cameraWaterCheckSphere.radius = 0.1f; + _cameraWaterCheckSphere.isTrigger = true; + + Rigidbody _cameraWaterCheckRb = _cameraWaterCheckObject.AddComponent (); + _cameraWaterCheckRb.useGravity = false; + _cameraWaterCheckRb.isKinematic = true; + + _cameraWaterCheck = _cameraWaterCheckObject.AddComponent (); + + prevPosition = transform.position; + + if (viewTransform == null) + viewTransform = Camera.main.transform; + + if (playerRotationTransform == null && transform.childCount > 0) + playerRotationTransform = transform.GetChild (0); + + _collider = gameObject.GetComponent (); + + if (_collider != null) + GameObject.Destroy (_collider); + + // rigidbody is required to collide with triggers + rb = gameObject.GetComponent (); + if (rb == null) + rb = gameObject.AddComponent (); + + allowCrouch = crouchingEnabled; + + rb.isKinematic = true; + rb.useGravity = false; + rb.angularDrag = 0f; + rb.drag = 0f; + rb.mass = weight; + + + switch (collisionType) { + + // Box collider + case ColliderType.Box: + + _collider = _colliderObject.AddComponent (); + + var boxc = (BoxCollider)_collider; + boxc.size = colliderSize; + + defaultHeight = boxc.size.y; + + break; + + // Capsule collider + case ColliderType.Capsule: + + _collider = _colliderObject.AddComponent (); + + var capc = (CapsuleCollider)_collider; + capc.height = colliderSize.y; + capc.radius = colliderSize.x / 2f; + + defaultHeight = capc.height; + + break; + + } + + _moveData.rigidbodyPushForce = rigidbodyPushForce; + + _moveData.slidingEnabled = slidingEnabled; + + _moveData.playerTransform = transform; + _moveData.viewTransform = viewTransform; + _moveData.viewTransformDefaultLocalPos = viewTransform.localPosition; + + _moveData.defaultHeight = defaultHeight; + _moveData.crouchingHeight = crouchingHeightMultiplier; + _moveData.crouchingSpeed = crouchingSpeed; + + _collider.isTrigger = !solidCollider; + _moveData.origin = transform.position; + _startPosition = transform.position; + + } + + private void Update () { + + _colliderObject.transform.rotation = Quaternion.identity; + + + //UpdateTestBinds (); + UpdateMoveData (); + + // Previous movement code + Vector3 positionalMovement = transform.position - prevPosition; + transform.position = prevPosition; + moveData.origin += positionalMovement; + + // Triggers + if (numberOfTriggers != triggers.Count) { + numberOfTriggers = triggers.Count; + + underwater = false; + triggers.RemoveAll (item => item == null); + foreach (Collider trigger in triggers) { + + if (trigger == null) + continue; + + if (trigger.GetComponentInParent ()) + underwater = true; + + } + + } + + _moveData.cameraUnderwater = _cameraWaterCheck.IsUnderwater (); + _cameraWaterCheckObject.transform.position = viewTransform.position; + moveData.underwater = underwater; + + if (allowCrouch) + _controller.Crouch (this, movementConfig, Time.deltaTime); + + _controller.ProcessMovement (this, movementConfig, Time.deltaTime); + + transform.position = moveData.origin; + prevPosition = transform.position; + + _colliderObject.transform.rotation = Quaternion.identity; + + } + + private void UpdateTestBinds () { + + if (Input.GetKeyDown (KeyCode.Backspace)) + ResetPosition (); + + } + + private void ResetPosition () { + + moveData.velocity = Vector3.zero; + moveData.origin = _startPosition; + + } + + private void UpdateMoveData () { + + _moveData.verticalAxis = Input.GetAxisRaw ("Vertical"); + _moveData.horizontalAxis = Input.GetAxisRaw ("Horizontal"); + + _moveData.sprinting = Input.GetButton ("Sprint"); + + if (Input.GetButtonDown ("Crouch")) + _moveData.crouching = true; + + if (!Input.GetButton ("Crouch")) + _moveData.crouching = false; + + bool moveLeft = _moveData.horizontalAxis < 0f; + bool moveRight = _moveData.horizontalAxis > 0f; + bool moveFwd = _moveData.verticalAxis > 0f; + bool moveBack = _moveData.verticalAxis < 0f; + bool jump = Input.GetButton ("Jump"); + + if (!moveLeft && !moveRight) + _moveData.sideMove = 0f; + else if (moveLeft) + _moveData.sideMove = -moveConfig.acceleration; + else if (moveRight) + _moveData.sideMove = moveConfig.acceleration; + + if (!moveFwd && !moveBack) + _moveData.forwardMove = 0f; + else if (moveFwd) + _moveData.forwardMove = moveConfig.acceleration; + else if (moveBack) + _moveData.forwardMove = -moveConfig.acceleration; + + if (Input.GetButtonDown ("Jump")) + _moveData.wishJump = true; + + if (!Input.GetButton ("Jump")) + _moveData.wishJump = false; + + _moveData.viewAngles = _angles; + + } + + private void DisableInput () { + + _moveData.verticalAxis = 0f; + _moveData.horizontalAxis = 0f; + _moveData.sideMove = 0f; + _moveData.forwardMove = 0f; + _moveData.wishJump = false; + + } + + /// + /// + /// + /// + /// + /// + /// + public static float ClampAngle (float angle, float from, float to) { + + if (angle < 0f) + angle = 360 + angle; + + if (angle > 180f) + return Mathf.Max (angle, 360 + from); + + return Mathf.Min (angle, to); + + } + + private void OnTriggerEnter (Collider other) { + + if (!triggers.Contains (other)) + triggers.Add (other); + + } + + private void OnTriggerExit (Collider other) { + + if (triggers.Contains (other)) + triggers.Remove (other); + + } + + private void OnCollisionStay (Collision collision) { + + if (collision.rigidbody == null) + return; + + Vector3 relativeVelocity = collision.relativeVelocity * collision.rigidbody.mass / 50f; + Vector3 impactVelocity = new Vector3 (relativeVelocity.x * 0.0025f, relativeVelocity.y * 0.00025f, relativeVelocity.z * 0.0025f); + + float maxYVel = Mathf.Max (moveData.velocity.y, 10f); + Vector3 newVelocity = new Vector3 (moveData.velocity.x + impactVelocity.x, Mathf.Clamp (moveData.velocity.y + Mathf.Clamp (impactVelocity.y, -0.5f, 0.5f), -maxYVel, maxYVel), moveData.velocity.z + impactVelocity.z); + + newVelocity = Vector3.ClampMagnitude (newVelocity, Mathf.Max (moveData.velocity.magnitude, 30f)); + moveData.velocity = newVelocity; + + } + + } + +} + diff --git a/Modified fragsurf/Movement/SurfCharacter.cs.meta b/Modified fragsurf/Movement/SurfCharacter.cs.meta new file mode 100644 index 0000000..b723fe5 --- /dev/null +++ b/Modified fragsurf/Movement/SurfCharacter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 601d4686cc0b70d45a98271d52094850 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/SurfController.cs b/Modified fragsurf/Movement/SurfController.cs new file mode 100644 index 0000000..70442d3 --- /dev/null +++ b/Modified fragsurf/Movement/SurfController.cs @@ -0,0 +1,651 @@ +using UnityEngine; +using Fragsurf.TraceUtil; + +namespace Fragsurf.Movement { + public class SurfController { + + ///// Fields ///// + + [HideInInspector] public Transform playerTransform; + private ISurfControllable _surfer; + private MovementConfig _config; + private float _deltaTime; + + public bool jumping = false; + public bool crouching = false; + public float speed = 0f; + + public Transform camera; + public float cameraYPos = 0f; + + private float slideSpeedCurrent = 0f; + private Vector3 slideDirection = Vector3.forward; + + private bool sliding = false; + private bool wasSliding = false; + private float slideDelay = 0f; + + private bool uncrouchDown = false; + private float crouchLerp = 0f; + + private float frictionMult = 1f; + + ///// Methods ///// + + Vector3 groundNormal = Vector3.up; + + /// + /// + /// + public void ProcessMovement (ISurfControllable surfer, MovementConfig config, float deltaTime) { + + // cache instead of passing around parameters + _surfer = surfer; + _config = config; + _deltaTime = deltaTime; + + if (!_surfer.moveData.underwater) { + + if (_surfer.moveData.velocity.y <= 0f) + jumping = false; + + // apply gravity + if (_surfer.groundObject == null) { + + _surfer.moveData.velocity.y -= (_surfer.moveData.gravityFactor * _config.gravity * _deltaTime); + _surfer.moveData.velocity.y += _surfer.baseVelocity.y * _deltaTime; + + } + + // input velocity, check for ground + CheckGrounded (); + CalculateMovementVelocity (); + + } else { + + // Do underwater logic + UnderwaterPhysics (); + + } + + float yVel = _surfer.moveData.velocity.y; + _surfer.moveData.velocity.y = 0f; + _surfer.moveData.velocity = Vector3.ClampMagnitude (_surfer.moveData.velocity, _config.maxVelocity); + speed = _surfer.moveData.velocity.magnitude; + _surfer.moveData.velocity.y = yVel; + + float maxDistPerFrame = 1f; + Vector3 velocityThisFrame = _surfer.moveData.velocity * _deltaTime; + float velocityDistLeft = velocityThisFrame.magnitude; + float initialVel = velocityDistLeft; + while (velocityDistLeft > 0f) { + + float amountThisLoop = Mathf.Min (maxDistPerFrame, velocityDistLeft); + velocityDistLeft -= amountThisLoop; + + // increment origin + Vector3 velThisLoop = velocityThisFrame * (amountThisLoop / initialVel); + _surfer.moveData.origin += velThisLoop; + + // don't penetrate walls + SurfPhysics.ResolveCollisions (_surfer.collider, ref _surfer.moveData.origin, ref _surfer.moveData.velocity, _surfer.moveData.rigidbodyPushForce); + + } + + _surfer.moveData.groundedTemp = _surfer.moveData.grounded; + + _surfer = null; + + } + + /// + /// + /// + private void CalculateMovementVelocity () { + switch (_surfer.moveType) { + + case MoveType.Walk: + + if (_surfer.groundObject == null) { + + /* + // AIR MOVEMENT + */ + + wasSliding = false; + + // apply movement from input + _surfer.moveData.velocity += AirInputMovement (); + + // let the magic happen + SurfPhysics.Reflect (ref _surfer.moveData.velocity, _surfer.collider, _surfer.moveData.origin, _deltaTime); + + } else { + + /* + // GROUND MOVEMENT + */ + + // Sliding + if (!wasSliding) { + + slideDirection = new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z).normalized; + slideSpeedCurrent = Mathf.Max (_config.maximumSlideSpeed, new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z).magnitude); + + } + + sliding = false; + if (_surfer.moveData.velocity.magnitude > _config.minimumSlideSpeed && _surfer.moveData.slidingEnabled && _surfer.moveData.crouching && slideDelay <= 0f) { + + if (!wasSliding) + slideSpeedCurrent = Mathf.Clamp (slideSpeedCurrent * _config.slideSpeedMultiplier, _config.minimumSlideSpeed, _config.maximumSlideSpeed); + + sliding = true; + wasSliding = true; + SlideMovement (); + return; + + } else { + + if (slideDelay > 0f) + slideDelay -= _deltaTime; + + if (wasSliding) + slideDelay = _config.slideDelay; + + wasSliding = false; + + } + + float fric = crouching ? _config.crouchFriction : _config.friction; + float accel = crouching ? _config.crouchAcceleration : _config.acceleration; + float decel = crouching ? _config.crouchDeceleration : _config.deceleration; + + // Get movement directions + Vector3 forward = Vector3.Cross (groundNormal, -playerTransform.right); + Vector3 right = Vector3.Cross (groundNormal, forward); + + float speed = _surfer.moveData.sprinting ? _config.sprintSpeed : _config.walkSpeed; + if (crouching) + speed = _config.crouchSpeed; + + Vector3 _wishDir; + + // Jump and friction + if (_surfer.moveData.wishJump) { + + ApplyFriction (0.0f, true, true); + Jump (); + return; + + } else { + + ApplyFriction (1.0f * frictionMult, true, true); + + } + + float forwardMove = _surfer.moveData.verticalAxis; + float rightMove = _surfer.moveData.horizontalAxis; + + _wishDir = forwardMove * forward + rightMove * right; + _wishDir.Normalize (); + Vector3 moveDirNorm = _wishDir; + + Vector3 forwardVelocity = Vector3.Cross (groundNormal, Quaternion.AngleAxis (-90, Vector3.up) * new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z)); + + // Set the target speed of the player + float _wishSpeed = _wishDir.magnitude; + _wishSpeed *= speed; + + // Accelerate + float yVel = _surfer.moveData.velocity.y; + Accelerate (_wishDir, _wishSpeed, accel * Mathf.Min (frictionMult, 1f), false); + + float maxVelocityMagnitude = _config.maxVelocity; + _surfer.moveData.velocity = Vector3.ClampMagnitude (new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z), maxVelocityMagnitude); + _surfer.moveData.velocity.y = yVel; + + // Calculate how much slopes should affect movement + float yVelocityNew = forwardVelocity.normalized.y * new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z).magnitude; + + // Apply the Y-movement from slopes + _surfer.moveData.velocity.y = yVelocityNew * (_wishDir.y < 0f ? 1.2f : 1.0f); + float removableYVelocity = _surfer.moveData.velocity.y - yVelocityNew; + + } + + break; + + } // END OF SWITCH STATEMENT + } + + private void UnderwaterPhysics () { + + _surfer.moveData.velocity = Vector3.Lerp (_surfer.moveData.velocity, Vector3.zero, _config.underwaterVelocityDampening * _deltaTime); + + // Gravity + if (!CheckGrounded ()) + _surfer.moveData.velocity.y -= _config.underwaterGravity * _deltaTime; + + // Swimming upwards + if (Input.GetButton ("Jump")) + _surfer.moveData.velocity.y += _config.swimUpSpeed * _deltaTime; + + float fric = _config.underwaterFriction; + float accel = _config.underwaterAcceleration; + float decel = _config.underwaterDeceleration; + + ApplyFriction (1f, true, false); + + // Get movement directions + Vector3 forward = Vector3.Cross (groundNormal, -playerTransform.right); + Vector3 right = Vector3.Cross (groundNormal, forward); + + float speed = _config.underwaterSwimSpeed; + + Vector3 _wishDir; + + float forwardMove = _surfer.moveData.verticalAxis; + float rightMove = _surfer.moveData.horizontalAxis; + + _wishDir = forwardMove * forward + rightMove * right; + _wishDir.Normalize (); + Vector3 moveDirNorm = _wishDir; + + Vector3 forwardVelocity = Vector3.Cross (groundNormal, Quaternion.AngleAxis (-90, Vector3.up) * new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z)); + + // Set the target speed of the player + float _wishSpeed = _wishDir.magnitude; + _wishSpeed *= speed; + + // Accelerate + float yVel = _surfer.moveData.velocity.y; + Accelerate (_wishDir, _wishSpeed, accel, false); + + float maxVelocityMagnitude = _config.maxVelocity; + _surfer.moveData.velocity = Vector3.ClampMagnitude (new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z), maxVelocityMagnitude); + _surfer.moveData.velocity.y = yVel; + + float yVelStored = _surfer.moveData.velocity.y; + _surfer.moveData.velocity.y = 0f; + + // Calculate how much slopes should affect movement + float yVelocityNew = forwardVelocity.normalized.y * new Vector3 (_surfer.moveData.velocity.x, 0f, _surfer.moveData.velocity.z).magnitude; + + // Apply the Y-movement from slopes + _surfer.moveData.velocity.y = Mathf.Min (Mathf.Max (0f, yVelocityNew) + yVelStored, speed); + + // Jumping out of water + bool movingForwards = playerTransform.InverseTransformVector (_surfer.moveData.velocity).z > 0f; + Trace waterJumpTrace = TraceBounds (playerTransform.position, playerTransform.position + playerTransform.forward * 0.1f, SurfPhysics.groundLayerMask); + if (waterJumpTrace.hitCollider != null && Vector3.Angle (Vector3.up, waterJumpTrace.planeNormal) >= _config.slopeLimit && Input.GetButton ("Jump") && !_surfer.moveData.cameraUnderwater && movingForwards) + _surfer.moveData.velocity.y = Mathf.Max (_surfer.moveData.velocity.y, _config.jumpForce); + + } + + private void Accelerate (Vector3 wishDir, float wishSpeed, float acceleration, bool yMovement) { + + // Initialise variables + float _addSpeed; + float _accelerationSpeed; + float _currentSpeed; + + // again, no idea + _currentSpeed = Vector3.Dot (_surfer.moveData.velocity, wishDir); + _addSpeed = wishSpeed - _currentSpeed; + + // If you're not actually increasing your speed, stop here. + if (_addSpeed <= 0) + return; + + // won't bother trying to understand any of this, really + _accelerationSpeed = Mathf.Min (acceleration * _deltaTime * wishSpeed, _addSpeed); + + // Add the velocity. + _surfer.moveData.velocity.x += _accelerationSpeed * wishDir.x; + if (yMovement) { _surfer.moveData.velocity.y += _accelerationSpeed * wishDir.y; } + _surfer.moveData.velocity.z += _accelerationSpeed * wishDir.z; + + } + + private void ApplyFriction (float t, bool yAffected, bool grounded) { + + // Initialise variables + Vector3 _vel = _surfer.moveData.velocity; + float _speed; + float _newSpeed; + float _control; + float _drop; + + // Set Y to 0, speed to the magnitude of movement and drop to 0. I think drop is the amount of speed that is lost, but I just stole this from the internet, idk. + _vel.y = 0.0f; + _speed = _vel.magnitude; + _drop = 0.0f; + + float fric = crouching ? _config.crouchFriction : _config.friction; + float accel = crouching ? _config.crouchAcceleration : _config.acceleration; + float decel = crouching ? _config.crouchDeceleration : _config.deceleration; + + // Only apply friction if the player is grounded + if (grounded) { + + // i honestly have no idea what this does tbh + _vel.y = _surfer.moveData.velocity.y; + _control = _speed < decel ? decel : _speed; + _drop = _control * fric * _deltaTime * t; + + } + + // again, no idea, but comments look cool + _newSpeed = Mathf.Max (_speed - _drop, 0f); + if (_speed > 0.0f) + _newSpeed /= _speed; + + // Set the end-velocity + _surfer.moveData.velocity.x *= _newSpeed; + if (yAffected == true) { _surfer.moveData.velocity.y *= _newSpeed; } + _surfer.moveData.velocity.z *= _newSpeed; + + } + + /// + /// + /// + /// + private Vector3 AirInputMovement () { + + Vector3 wishVel, wishDir; + float wishSpeed; + + GetWishValues (out wishVel, out wishDir, out wishSpeed); + + if (_config.clampAirSpeed && (wishSpeed != 0f && (wishSpeed > _config.maxSpeed))) { + + wishVel = wishVel * (_config.maxSpeed / wishSpeed); + wishSpeed = _config.maxSpeed; + + } + + return SurfPhysics.AirAccelerate (_surfer.moveData.velocity, wishDir, wishSpeed, _config.airAcceleration, _config.airCap, _deltaTime); + + } + + /// + /// + /// + /// + /// + /// + private void GetWishValues (out Vector3 wishVel, out Vector3 wishDir, out float wishSpeed) { + + wishVel = Vector3.zero; + wishDir = Vector3.zero; + wishSpeed = 0f; + + Vector3 forward = _surfer.forward, + right = _surfer.right; + + forward [1] = 0; + right [1] = 0; + forward.Normalize (); + right.Normalize (); + + for (int i = 0; i < 3; i++) + wishVel [i] = forward [i] * _surfer.moveData.forwardMove + right [i] * _surfer.moveData.sideMove; + wishVel [1] = 0; + + wishSpeed = wishVel.magnitude; + wishDir = wishVel.normalized; + + } + + /// + /// + /// + /// + /// + private void Jump () { + + if (!_config.autoBhop) + _surfer.moveData.wishJump = false; + + _surfer.moveData.velocity.y += _config.jumpForce; + jumping = true; + + } + + /// + /// + /// + private bool CheckGrounded () { + + _surfer.moveData.surfaceFriction = 1f; + var movingUp = _surfer.moveData.velocity.y > 0f; + var trace = TraceToFloor (); + + float groundSteepness = Vector3.Angle (Vector3.up, trace.planeNormal); + + if (trace.hitCollider == null || groundSteepness > _config.slopeLimit || (jumping && _surfer.moveData.velocity.y > 0f)) { + + SetGround (null); + + if (movingUp && _surfer.moveType != MoveType.Noclip) + _surfer.moveData.surfaceFriction = _config.airFriction; + + return false; + + } else { + + groundNormal = trace.planeNormal; + SetGround (trace.hitCollider.gameObject); + return true; + + } + + } + + /// + /// + /// + /// + private void SetGround (GameObject obj) { + + if (obj != null) { + + _surfer.groundObject = obj; + _surfer.moveData.velocity.y = 0; + + } else + _surfer.groundObject = null; + + } + + /// + /// + /// + /// + /// + /// + /// + private Trace TraceBounds (Vector3 start, Vector3 end, int layerMask) { + + return Tracer.TraceCollider (_surfer.collider, start, end, layerMask); + + } + + /// + /// + /// + /// + private Trace TraceToFloor () { + + var down = _surfer.moveData.origin; + down.y -= 0.1f; + + return Tracer.TraceCollider (_surfer.collider, _surfer.moveData.origin, down, SurfPhysics.groundLayerMask); + + } + + public void Crouch (ISurfControllable surfer, MovementConfig config, float deltaTime) { + + _surfer = surfer; + _config = config; + _deltaTime = deltaTime; + + if (_surfer == null) + return; + + if (_surfer.collider == null) + return; + + bool grounded = _surfer.groundObject != null; + bool wantsToCrouch = _surfer.moveData.crouching; + + float crouchingHeight = Mathf.Clamp (_surfer.moveData.crouchingHeight, 0.01f, 1f); + float heightDifference = _surfer.moveData.defaultHeight - _surfer.moveData.defaultHeight * crouchingHeight; + + if (grounded) + uncrouchDown = false; + + // Crouching input + if (grounded) + crouchLerp = Mathf.Lerp (crouchLerp, wantsToCrouch ? 1f : 0f, _deltaTime * _surfer.moveData.crouchingSpeed); + else if (!grounded && !wantsToCrouch && crouchLerp < 0.95f) + crouchLerp = 0f; + else if (!grounded && wantsToCrouch) + crouchLerp = 1f; + + // Collider and position changing + if (crouchLerp > 0.9f && !crouching) { + + // Begin crouching + crouching = true; + if (_surfer.collider.GetType () == typeof (BoxCollider)) { + + // Box collider + BoxCollider boxCollider = (BoxCollider)_surfer.collider; + boxCollider.size = new Vector3 (boxCollider.size.x, _surfer.moveData.defaultHeight * crouchingHeight, boxCollider.size.z); + + } else if (_surfer.collider.GetType () == typeof (CapsuleCollider)) { + + // Capsule collider + CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider; + capsuleCollider.height = _surfer.moveData.defaultHeight * crouchingHeight; + + } + + // Move position and stuff + _surfer.moveData.origin += heightDifference / 2 * (grounded ? Vector3.down : Vector3.up); + foreach (Transform child in playerTransform) { + + if (child == _surfer.moveData.viewTransform) + continue; + + child.localPosition = new Vector3 (child.localPosition.x, child.localPosition.y * crouchingHeight, child.localPosition.z); + + } + + uncrouchDown = !grounded; + + } else if (crouching) { + + // Check if the player can uncrouch + bool canUncrouch = true; + if (_surfer.collider.GetType () == typeof (BoxCollider)) { + + // Box collider + BoxCollider boxCollider = (BoxCollider)_surfer.collider; + Vector3 halfExtents = boxCollider.size * 0.5f; + Vector3 startPos = boxCollider.transform.position; + Vector3 endPos = boxCollider.transform.position + (uncrouchDown ? Vector3.down : Vector3.up) * heightDifference; + + Trace trace = Tracer.TraceBox (startPos, endPos, halfExtents, boxCollider.contactOffset, SurfPhysics.groundLayerMask); + + if (trace.hitCollider != null) + canUncrouch = false; + + } else if (_surfer.collider.GetType () == typeof (CapsuleCollider)) { + + // Capsule collider + CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider; + Vector3 point1 = capsuleCollider.center + Vector3.up * capsuleCollider.height * 0.5f; + Vector3 point2 = capsuleCollider.center + Vector3.down * capsuleCollider.height * 0.5f; + Vector3 startPos = capsuleCollider.transform.position; + Vector3 endPos = capsuleCollider.transform.position + (uncrouchDown ? Vector3.down : Vector3.up) * heightDifference; + + Trace trace = Tracer.TraceCapsule (point1, point2, capsuleCollider.radius, startPos, endPos, capsuleCollider.contactOffset, SurfPhysics.groundLayerMask); + + if (trace.hitCollider != null) + canUncrouch = false; + + } + + // Uncrouch + if (canUncrouch && crouchLerp <= 0.9f) { + + crouching = false; + if (_surfer.collider.GetType () == typeof (BoxCollider)) { + + // Box collider + BoxCollider boxCollider = (BoxCollider)_surfer.collider; + boxCollider.size = new Vector3 (boxCollider.size.x, _surfer.moveData.defaultHeight, boxCollider.size.z); + + } else if (_surfer.collider.GetType () == typeof (CapsuleCollider)) { + + // Capsule collider + CapsuleCollider capsuleCollider = (CapsuleCollider)_surfer.collider; + capsuleCollider.height = _surfer.moveData.defaultHeight; + + } + + // Move position and stuff + _surfer.moveData.origin += heightDifference / 2 * (uncrouchDown ? Vector3.down : Vector3.up); + foreach (Transform child in playerTransform) { + + child.localPosition = new Vector3 (child.localPosition.x, child.localPosition.y / crouchingHeight, child.localPosition.z); + + } + + } + + if (!canUncrouch) + crouchLerp = 1f; + + } + + // Changing camera position + if (!crouching) + _surfer.moveData.viewTransform.localPosition = Vector3.Lerp (_surfer.moveData.viewTransformDefaultLocalPos, _surfer.moveData.viewTransformDefaultLocalPos * crouchingHeight + Vector3.down * heightDifference * 0.5f, crouchLerp); + else + _surfer.moveData.viewTransform.localPosition = Vector3.Lerp (_surfer.moveData.viewTransformDefaultLocalPos - Vector3.down * heightDifference * 0.5f, _surfer.moveData.viewTransformDefaultLocalPos * crouchingHeight, crouchLerp); + + } + + void SlideMovement () { + + // Gradually change direction + slideDirection += new Vector3 (groundNormal.x, 0f, groundNormal.z) * slideSpeedCurrent * _deltaTime; + slideDirection = slideDirection.normalized; + + // Set direction + Vector3 slideForward = Vector3.Cross (groundNormal, Quaternion.AngleAxis (-90, Vector3.up) * slideDirection); + + // Set the velocity + slideSpeedCurrent -= _config.slideFriction * _deltaTime; + slideSpeedCurrent = Mathf.Clamp (slideSpeedCurrent, 0f, _config.maximumSlideSpeed); + slideSpeedCurrent -= (slideForward * slideSpeedCurrent).y * _deltaTime * _config.downhillSlideSpeedMultiplier; // Accelerate downhill (-y = downward, - * - = +) + + _surfer.moveData.velocity = slideForward * slideSpeedCurrent; + + // Jump + if (_surfer.moveData.wishJump && slideSpeedCurrent < _config.minimumSlideSpeed * _config.slideSpeedMultiplier) { + + Jump (); + return; + + } + + } + + } +} diff --git a/Modified fragsurf/Movement/SurfController.cs.meta b/Modified fragsurf/Movement/SurfController.cs.meta new file mode 100644 index 0000000..633300c --- /dev/null +++ b/Modified fragsurf/Movement/SurfController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9877690760780b441aeafc5ca145fd3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Movement/SurfPhysics.cs b/Modified fragsurf/Movement/SurfPhysics.cs new file mode 100644 index 0000000..3424fa1 --- /dev/null +++ b/Modified fragsurf/Movement/SurfPhysics.cs @@ -0,0 +1,428 @@ +using UnityEngine; +using Fragsurf.TraceUtil; + +namespace Fragsurf.Movement { + public class SurfPhysics { + + ///// Fields ///// + + /// + /// Change this if your ground is on a different layer + /// + public static int groundLayerMask = LayerMask.GetMask (new string[] { "Default", "Ground", "Player clip" }); //(1 << 0); + + private static Collider[] _colliders = new Collider [maxCollisions]; + private static Vector3[] _planes = new Vector3 [maxClipPlanes]; + public const float HU2M = 52.4934383202f; + private const int maxCollisions = 128; + private const int maxClipPlanes = 5; + private const int numBumps = 1; + + public const float SurfSlope = 0.7f; + + ///// Methods ///// + + /// + /// + /// + /// + /// + /// + /// http://www.00jknight.com/blog/unity-character-controller + public static void ResolveCollisions (Collider collider, ref Vector3 origin, ref Vector3 velocity, float rigidbodyPushForce) { + + // manual collision resolving + int numOverlaps = 0; + if (collider is CapsuleCollider) { + + var capc = collider as CapsuleCollider; + + Vector3 point1, point2; + GetCapsulePoints (capc, origin, out point1, out point2); + + numOverlaps = Physics.OverlapCapsuleNonAlloc (point1, point2, capc.radius, + _colliders, groundLayerMask, QueryTriggerInteraction.Ignore); + + } else if (collider is BoxCollider) { + + numOverlaps = Physics.OverlapBoxNonAlloc (origin, collider.bounds.extents, _colliders, + Quaternion.identity, groundLayerMask, QueryTriggerInteraction.Ignore); + + } + + for (int i = 0; i < numOverlaps; i++) { + + Vector3 direction; + float distance; + + if (Physics.ComputePenetration (collider, origin, + Quaternion.identity, _colliders [i], _colliders [i].transform.position, + _colliders [i].transform.rotation, out direction, out distance)) { + + direction.Normalize (); + Vector3 penetrationVector = direction * distance; + Vector3 velocityProjected = Vector3.Project (velocity, -direction); + velocityProjected.y = 0; // don't touch y velocity, we need it to calculate fall damage elsewhere + origin += penetrationVector; + velocity -= velocityProjected; + + Rigidbody rb = _colliders [i].GetComponentInParent (); + if (rb) + if (!rb.isKinematic) + rb.AddForceAtPosition (velocityProjected * rigidbodyPushForce, origin, ForceMode.Impulse); + + } + + } + + } + + /// + /// + /// + public static void Friction (ref Vector3 velocity, float stopSpeed, float friction, float deltaTime) { + + var speed = velocity.magnitude; + + if (speed < 0.0001905f) + return; + + var drop = 0f; + + // apply ground friction + var control = (speed < stopSpeed) ? stopSpeed : speed; + drop += control * friction * deltaTime; + + // scale the velocity + var newspeed = speed - drop; + if (newspeed < 0) + newspeed = 0; + + if (newspeed != speed) { + + newspeed /= speed; + velocity *= newspeed; + + } + + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3 AirAccelerate (Vector3 velocity, Vector3 wishdir, float wishspeed, float accel, float airCap, float deltaTime) { + + var wishspd = wishspeed; + + // Cap speed + wishspd = Mathf.Min (wishspd, airCap); + + // Determine veer amount + var currentspeed = Vector3.Dot (velocity, wishdir); + + // See how much to add + var addspeed = wishspd - currentspeed; + + // If not adding any, done. + if (addspeed <= 0) + return Vector3.zero; + + // Determine acceleration speed after acceleration + var accelspeed = accel * wishspeed * deltaTime; + + // Cap it + accelspeed = Mathf.Min (accelspeed, addspeed); + + var result = Vector3.zero; + + // Adjust pmove vel. + for (int i = 0; i < 3; i++) + result [i] += accelspeed * wishdir [i]; + + return result; + + } + + /// + /// + /// + /// + /// + /// + /// + public static Vector3 Accelerate (Vector3 currentVelocity, Vector3 wishdir, float wishspeed, float accel, float deltaTime, float surfaceFriction) { + + // See if we are changing direction a bit + var currentspeed = Vector3.Dot (currentVelocity, wishdir); + + // Reduce wishspeed by the amount of veer. + var addspeed = wishspeed - currentspeed; + + // If not going to add any speed, done. + if (addspeed <= 0) + return Vector3.zero; + + // Determine amount of accleration. + var accelspeed = accel * deltaTime * wishspeed * surfaceFriction; + + // Cap at addspeed + if (accelspeed > addspeed) + accelspeed = addspeed; + + var result = Vector3.zero; + + // Adjust velocity. + for (int i = 0; i < 3; i++) + result [i] += accelspeed * wishdir [i]; + + return result; + + } + + /// + /// + /// + /// + /// + /// + /// + /// + public static int Reflect (ref Vector3 velocity, Collider collider, Vector3 origin, float deltaTime) { + + float d; + var newVelocity = Vector3.zero; + var blocked = 0; // Assume not blocked + var numplanes = 0; // and not sliding along any planes + var originalVelocity = velocity; // Store original velocity + var primalVelocity = velocity; + + var allFraction = 0f; + var timeLeft = deltaTime; // Total time for this movement operation. + + for (int bumpcount = 0; bumpcount < numBumps; bumpcount++) { + + if (velocity.magnitude == 0f) + break; + + // Assume we can move all the way from the current origin to the + // end point. + var end = VectorExtensions.VectorMa (origin, timeLeft, velocity); + var trace = Tracer.TraceCollider (collider, origin, end, groundLayerMask); + + allFraction += trace.fraction; + + if (trace.fraction > 0) { + + // actually covered some distance + originalVelocity = velocity; + numplanes = 0; + + } + + // If we covered the entire distance, we are done + // and can return. + if (trace.fraction == 1) + break; // moved the entire distance + + // If the plane we hit has a high z component in the normal, then + // it's probably a floor + if (trace.planeNormal.y > SurfSlope) + blocked |= 1; // floor + + // If the plane has a zero z component in the normal, then it's a + // step or wall + if (trace.planeNormal.y == 0) + blocked |= 2; // step / wall + + // Reduce amount of m_flFrameTime left by total time left * fraction + // that we covered. + timeLeft -= timeLeft * trace.fraction; + + // Did we run out of planes to clip against? + if (numplanes >= maxClipPlanes) { + + // this shouldn't really happen + // Stop our movement if so. + velocity = Vector3.zero; + //Con_DPrintf("Too many planes 4\n"); + break; + + } + + // Set up next clipping plane + _planes [numplanes] = trace.planeNormal; + numplanes++; + + // modify original_velocity so it parallels all of the clip planes + // + + // reflect player velocity + // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place + // and pressing forward and nobody was really using this bounce/reflection feature anyway... + if (numplanes == 1) { + + for (int i = 0; i < numplanes; i++) { + + if (_planes [i] [1] > SurfSlope) { + + // floor or slope + return blocked; + //ClipVelocity(originalVelocity, _planes[i], ref newVelocity, 1f); + //originalVelocity = newVelocity; + + } else + ClipVelocity (originalVelocity, _planes [i], ref newVelocity, 1f); + + } + + velocity = newVelocity; + originalVelocity = newVelocity; + + } else { + + int i = 0; + for (i = 0; i < numplanes; i++) { + + ClipVelocity (originalVelocity, _planes [i], ref velocity, 1); + + int j = 0; + + for (j = 0; j < numplanes; j++) { + if (j != i) { + + // Are we now moving against this plane? + if (Vector3.Dot (velocity, _planes [j]) < 0) + break; + + } + } + + if (j == numplanes) // Didn't have to clip, so we're ok + break; + + } + + // Did we go all the way through plane set + if (i != numplanes) { // go along this plane + // pmove.velocity is set in clipping call, no need to set again. + ; + } else { // go along the crease + + if (numplanes != 2) { + + velocity = Vector3.zero; + break; + + } + + var dir = Vector3.Cross (_planes [0], _planes [1]).normalized; + d = Vector3.Dot (dir, velocity); + velocity = dir * d; + + } + + // + // if original velocity is against the original velocity, stop dead + // to avoid tiny occilations in sloping corners + // + d = Vector3.Dot (velocity, primalVelocity); + if (d <= 0f) { + + //Con_DPrintf("Back\n"); + velocity = Vector3.zero; + break; + + } + + } + + } + + if (allFraction == 0f) + velocity = Vector3.zero; + + // Check if they slammed into a wall + //float fSlamVol = 0.0f; + + //var primal2dLen = new Vector2(primal_velocity.x, primal_velocity.z).magnitude; + //var vel2dLen = new Vector2(_moveData.Velocity.x, _moveData.Velocity.z).magnitude; + //float fLateralStoppingAmount = primal2dLen - vel2dLen; + //if (fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED * 2.0f) + //{ + // fSlamVol = 1.0f; + //} + //else if (fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED) + //{ + // fSlamVol = 0.85f; + //} + + //PlayerRoughLandingEffects(fSlamVol); + + return blocked; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public static int ClipVelocity (Vector3 input, Vector3 normal, ref Vector3 output, float overbounce) { + + var angle = normal [1]; + var blocked = 0x00; // Assume unblocked. + + if (angle > 0) // If the plane that is blocking us has a positive z component, then assume it's a floor. + blocked |= 0x01; // + + if (angle == 0) // If the plane has no Z, it is vertical (wall/step) + blocked |= 0x02; // + + // Determine how far along plane to slide based on incoming direction. + var backoff = Vector3.Dot (input, normal) * overbounce; + + for (int i = 0; i < 3; i++) { + + var change = normal [i] * backoff; + output [i] = input [i] - change; + + } + + // iterate once to make sure we aren't still moving through the plane + float adjust = Vector3.Dot (output, normal); + if (adjust < 0.0f) { + + output -= (normal * adjust); + // Msg( "Adjustment = %lf\n", adjust ); + + } + + // Return blocking flags. + return blocked; + + } + + /// + /// + /// + /// + /// + public static void GetCapsulePoints (CapsuleCollider capc, Vector3 origin, out Vector3 p1, out Vector3 p2) { + + var distanceToPoints = capc.height / 2f - capc.radius; + p1 = origin + capc.center + Vector3.up * distanceToPoints; + p2 = origin + capc.center - Vector3.up * distanceToPoints; + + } + + } +} diff --git a/Modified fragsurf/Movement/SurfPhysics.cs.meta b/Modified fragsurf/Movement/SurfPhysics.cs.meta new file mode 100644 index 0000000..2dfc3cc --- /dev/null +++ b/Modified fragsurf/Movement/SurfPhysics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82894b74fd05a584385e994a8297661f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/PlayerAiming.cs b/Modified fragsurf/PlayerAiming.cs new file mode 100644 index 0000000..288cb26 --- /dev/null +++ b/Modified fragsurf/PlayerAiming.cs @@ -0,0 +1,77 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerAiming : MonoBehaviour { + + [Header ("References")] + public Transform bodyTransform = null; + + [Header ("Sensitivity")] + public float sensitivityMultiplier = 1f; + public float horizontalSensitivity = 1f; + public float verticalSensitivity = 1f; + + [Header ("Restrictions")] + public float minYRotation = -90f; + public float maxYRotation = 90f; + + // Rotation values + [HideInInspector] public float bodyRotation = 0f; + [HideInInspector] public Vector3 cameraRotation = Vector3.zero; + + private float bodyRotationTemp = 0f; + private Vector3 cameraRotationTemp = Vector3.zero; + + // Leaning + [HideInInspector] public float leanInput = 0f; + + // Sway + [HideInInspector] public float sway = 0f; + + void Start () { + + // Lock the mouse + Cursor.lockState = CursorLockMode.Locked; + Cursor.visible = false; + + } + + void Update () { + + Vector3 eulerAngles = transform.localEulerAngles; + + // Remove previous rotation + eulerAngles = new Vector3 (eulerAngles.x - cameraRotationTemp.x, eulerAngles.y, eulerAngles.z - cameraRotationTemp.z); + bodyTransform.eulerAngles -= cameraRotationTemp.y * Vector3.up; + + // Fix pausing + if (Time.timeScale == 0f) + return; + + // Input + float xMovement = Input.GetAxis ("Mouse X") * horizontalSensitivity * sensitivityMultiplier; + float yMovement = -Input.GetAxis ("Mouse Y") * verticalSensitivity * sensitivityMultiplier; + + // Rotate camera + cameraRotation = new Vector3 (Mathf.Clamp (cameraRotation.x + yMovement, minYRotation, maxYRotation), + cameraRotation.y + xMovement, + cameraRotation.z + sway); + + cameraRotation.z = Mathf.Lerp (cameraRotation.z, 0f, Time.deltaTime * 3f); + + // Apply rotation + Vector3 clampedRotation = new Vector3 (Mathf.Clamp (cameraRotation.x, minYRotation, maxYRotation), + cameraRotation.y, + cameraRotation.z); + + eulerAngles = new Vector3 (eulerAngles.x + clampedRotation.x, eulerAngles.y, eulerAngles.z + clampedRotation.z); + bodyTransform.eulerAngles += Vector3.Scale (clampedRotation, new Vector3 (0f, 1f, 0f)); + cameraRotationTemp = clampedRotation; + + // Remove recoil + transform.localEulerAngles = eulerAngles; + + } + +} diff --git a/Modified fragsurf/PlayerAiming.cs.meta b/Modified fragsurf/PlayerAiming.cs.meta new file mode 100644 index 0000000..4e57b0d --- /dev/null +++ b/Modified fragsurf/PlayerAiming.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 604093a680e6d5a488206647cc35be23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/TraceUtil.meta b/Modified fragsurf/TraceUtil.meta new file mode 100644 index 0000000..7f4df13 --- /dev/null +++ b/Modified fragsurf/TraceUtil.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 94e9fff1435e72045a8916637b54c2a8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/TraceUtil/Trace.cs b/Modified fragsurf/TraceUtil/Trace.cs new file mode 100644 index 0000000..34ed8e5 --- /dev/null +++ b/Modified fragsurf/TraceUtil/Trace.cs @@ -0,0 +1,15 @@ +using UnityEngine; + +namespace Fragsurf.TraceUtil { + public struct Trace { + + public Vector3 startPos; + public Vector3 endPos; + public float fraction; + public bool startSolid; + public Collider hitCollider; + public Vector3 hitPoint; + public Vector3 planeNormal; + + } +} diff --git a/Modified fragsurf/TraceUtil/Trace.cs.meta b/Modified fragsurf/TraceUtil/Trace.cs.meta new file mode 100644 index 0000000..f21b0bb --- /dev/null +++ b/Modified fragsurf/TraceUtil/Trace.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d79906c8a32f894eac47445c9814b61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/TraceUtil/Tracer.cs b/Modified fragsurf/TraceUtil/Tracer.cs new file mode 100644 index 0000000..2bfd9e5 --- /dev/null +++ b/Modified fragsurf/TraceUtil/Tracer.cs @@ -0,0 +1,115 @@ +using UnityEngine; + +namespace Fragsurf.TraceUtil { + public class Tracer { + + /// + /// + /// + /// + /// + /// + /// + /// + public static Trace TraceCollider (Collider collider, Vector3 origin, Vector3 end, int layerMask) { + + if (collider is BoxCollider) { + + // Box collider trace + return TraceBox (origin, end, collider.bounds.extents, collider.contactOffset, layerMask); + + } else if (collider is CapsuleCollider) { + + // Capsule collider trace + var capc = (CapsuleCollider)collider; + + Vector3 point1, point2; + Movement.SurfPhysics.GetCapsulePoints (capc, origin, out point1, out point2); + + return TraceCapsule (point1, point2, capc.radius, origin, end, capc.contactOffset, layerMask); + + } + + throw new System.NotImplementedException ("Trace missing for collider: " + collider.GetType ()); + + } + + /// + /// + /// + /// + public static Trace TraceCapsule (Vector3 point1, Vector3 point2, float radius, Vector3 start, Vector3 destination, float contactOffset, int layerMask) { + + var result = new Trace () { + startPos = start, + endPos = destination + }; + + var longSide = Mathf.Sqrt (contactOffset * contactOffset + contactOffset * contactOffset); + radius *= (1f - contactOffset); + var direction = (destination - start).normalized; + var maxDistance = Vector3.Distance (start, destination) + longSide; + + RaycastHit hit; + if (Physics.CapsuleCast ( + point1: point1, + point2: point2, + radius: radius, + direction: direction, + hitInfo: out hit, + maxDistance: maxDistance, + layerMask: layerMask, + queryTriggerInteraction: QueryTriggerInteraction.Ignore)) { + + result.fraction = hit.distance / maxDistance; + result.hitCollider = hit.collider; + result.hitPoint = hit.point; + result.planeNormal = hit.normal; + + } else + result.fraction = 1; + + return result; + + } + + /// + /// + /// + /// + public static Trace TraceBox (Vector3 start, Vector3 destination, Vector3 extents, float contactOffset, int layerMask) { + + var result = new Trace () { + startPos = start, + endPos = destination + }; + + var longSide = Mathf.Sqrt (contactOffset * contactOffset + contactOffset * contactOffset); + var direction = (destination - start).normalized; + var maxDistance = Vector3.Distance (start, destination) + longSide; + extents *= (1f - contactOffset); + + RaycastHit hit; + if (Physics.BoxCast (center: start, + halfExtents: extents, + direction: direction, + orientation: Quaternion.identity, + maxDistance: maxDistance, + hitInfo: out hit, + layerMask: layerMask, + queryTriggerInteraction: QueryTriggerInteraction.Ignore)) { + + result.fraction = hit.distance / maxDistance; + result.hitCollider = hit.collider; + result.hitPoint = hit.point; + result.planeNormal = hit.normal; + + } else + result.fraction = 1; + + return result; + + } + + } +} \ No newline at end of file diff --git a/Modified fragsurf/TraceUtil/Tracer.cs.meta b/Modified fragsurf/TraceUtil/Tracer.cs.meta new file mode 100644 index 0000000..382c382 --- /dev/null +++ b/Modified fragsurf/TraceUtil/Tracer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b42ff46330f0b0d4696f4b054b34550f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Modified fragsurf/Water.cs b/Modified fragsurf/Water.cs new file mode 100644 index 0000000..b5fd5bb --- /dev/null +++ b/Modified fragsurf/Water.cs @@ -0,0 +1,10 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Water : MonoBehaviour { + + // This component is separate from the player's underwater movement. + // Feel free to add whatever you want in here, like a rigidbody buoyancy/floating system or something. + +} diff --git a/Modified fragsurf/Water.cs.meta b/Modified fragsurf/Water.cs.meta new file mode 100644 index 0000000..54952e3 --- /dev/null +++ b/Modified fragsurf/Water.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c652f03f4545c86499de323569052da5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: