diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 7594f02..637ef03 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -55,7 +55,6 @@ 6000.3.6f1 - diff --git a/Assets/Scenes/Experiment.unity b/Assets/Scenes/Experiment.unity index 24e561e..f8795ad 100644 --- a/Assets/Scenes/Experiment.unity +++ b/Assets/Scenes/Experiment.unity @@ -1659,58 +1659,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &908853548 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 908853550} - - component: {fileID: 908853549} - m_Layer: 0 - m_Name: Treat Spawner BL - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &908853549 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 908853548} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::Spawner - objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} - spawnInterval: 5 - maxAlive: 0 - spawnOnStart: 1 - repeatSpawns: 1 - launchForce: 0 - launchRandomAngle: 0 - spinSpeed: 0 ---- !u!4 &908853550 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 908853548} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -4.5, y: -2, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1063739947 GameObject: m_ObjectHideFlags: 0 @@ -2162,58 +2110,6 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 99cce68fc82caea44b5a140697be00a8, type: 3} ---- !u!1 &1466477811 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1466477813} - - component: {fileID: 1466477812} - m_Layer: 0 - m_Name: Treat Spawner TL - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1466477812 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1466477811} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::Spawner - objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} - spawnInterval: 5 - maxAlive: 0 - spawnOnStart: 1 - repeatSpawns: 1 - launchForce: 0 - launchRandomAngle: 0 - spinSpeed: 0 ---- !u!4 &1466477813 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1466477811} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -2.42, y: 2.93, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1654086541 GameObject: m_ObjectHideFlags: 0 @@ -2461,110 +2357,6 @@ PrefabInstance: m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 414ae949bae840c4589b38dd91c715e0, type: 3} ---- !u!1 &1759124602 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1759124604} - - component: {fileID: 1759124603} - m_Layer: 0 - m_Name: Treat Spawner TR - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1759124603 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1759124602} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::Spawner - objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} - spawnInterval: 5 - maxAlive: 0 - spawnOnStart: 1 - repeatSpawns: 1 - launchForce: 0 - launchRandomAngle: 0 - spinSpeed: 0 ---- !u!4 &1759124604 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1759124602} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 2.88, y: 2.69, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1830238251 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1830238253} - - component: {fileID: 1830238252} - m_Layer: 0 - m_Name: Treat Spawner BR - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &1830238252 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1830238251} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 14b0bf07aa1abc44a8ebd00cecacd6f4, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::Spawner - objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} - spawnInterval: 5 - maxAlive: 0 - spawnOnStart: 1 - repeatSpawns: 1 - launchForce: 0 - launchRandomAngle: 0 - spinSpeed: 0 ---- !u!4 &1830238253 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1830238251} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 4.5, y: -2, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2057686360 GameObject: m_ObjectHideFlags: 0 @@ -3000,13 +2792,13 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Assembly-CSharp::Spawner objectToSpawn: {fileID: 262983251238298495, guid: 80c527a86ad6fc34dbc73ee80c1f2951, type: 3} - spawnInterval: 5 + spawnInterval: 1.5 maxAlive: 0 spawnOnStart: 1 repeatSpawns: 1 launchForce: 4 launchRandomAngle: 360 - spinSpeed: 180 + spinSpeed: 100 --- !u!1001 &1760117322204329348 PrefabInstance: m_ObjectHideFlags: 0 @@ -3098,10 +2890,6 @@ SceneRoots: - {fileID: 1760117322204329348} - {fileID: 1277412258} - {fileID: 1227312797} - - {fileID: 1830238253} - - {fileID: 908853550} - - {fileID: 1466477813} - - {fileID: 1759124604} - {fileID: 792686806} - {fileID: 1685410085} - {fileID: 377513953} diff --git a/Assets/Scripts/PlayerPickupController.cs b/Assets/Scripts/PlayerPickupController.cs index 07d532b..83d724b 100644 --- a/Assets/Scripts/PlayerPickupController.cs +++ b/Assets/Scripts/PlayerPickupController.cs @@ -24,6 +24,11 @@ public class PlayerPickupController : MonoBehaviour public float pickupRange = 2.0f; public GameObject heldObject; + private Rigidbody2D heldBody; + private float heldBodyMass; + private float heldBodyGravity; + private RigidbodyType2D heldBodyType; + private bool heldBodySimulated; private PlayerPlatformerController platformerController; private PlayerStressController playerStressController; private bool isChargingThrow; @@ -163,9 +168,17 @@ public class PlayerPickupController : MonoBehaviour // Disable physics so it doesn't fall or collide with the player if (heldObject.TryGetComponent(out Rigidbody2D rb)) { + heldBody = rb; + heldBodyMass = rb.mass; + heldBodyGravity = rb.gravityScale; + heldBodyType = rb.bodyType; + heldBodySimulated = rb.simulated; + + rb.simulated = false; rb.bodyType = RigidbodyType2D.Kinematic; - rb.gravityScale = 0; - rb.mass = 0; + rb.gravityScale = 0f; + rb.linearVelocity = Vector2.zero; + rb.angularVelocity = 0f; } if (trick != null) @@ -195,11 +208,14 @@ public class PlayerPickupController : MonoBehaviour void DropObject(bool applyThrow) { // Re-enable physics - if (heldObject.TryGetComponent(out Rigidbody2D rb)) + if (heldBody != null) { - rb.bodyType = RigidbodyType2D.Dynamic; - rb.gravityScale = 1; - rb.linearVelocity = Vector2.zero; + heldBody.simulated = heldBodySimulated; + heldBody.bodyType = heldBodyType; + heldBody.gravityScale = heldBodyGravity; + heldBody.mass = heldBodyMass; + heldBody.linearVelocity = Vector2.zero; + heldBody.angularVelocity = 0f; } if (heldObject.TryGetComponent(out var trick)) { @@ -217,7 +233,7 @@ public class PlayerPickupController : MonoBehaviour heldPickup.enabled = true; } } - if (applyThrow && heldObject.TryGetComponent(out Rigidbody2D throwBody)) + if (applyThrow && heldBody != null) { var direction = 1f; if (platformerController != null && Mathf.Abs(platformerController.LastMoveX) > 0.01f) @@ -231,8 +247,9 @@ public class PlayerPickupController : MonoBehaviour charge01 = Mathf.Clamp01(heldTime / Mathf.Max(0.01f, throwChargeTime)); } var throwSpeed = Mathf.Lerp(minThrowSpeed, maxThrowSpeed, charge01); - throwBody.linearVelocity = new Vector2(direction * throwSpeed, 0f); - throwBody.angularVelocity = 0f; + var upwardSpeed = throwUpwardForce * charge01; + heldBody.linearVelocity = new Vector2(direction * throwSpeed, upwardSpeed); + heldBody.angularVelocity = 0f; } heldObject.transform.position += Vector3.up * dropClearance; Collider2D col = heldObject.GetComponent(); @@ -241,6 +258,7 @@ public class PlayerPickupController : MonoBehaviour // Unparent heldObject.transform.SetParent(null); heldObject = null; + heldBody = null; isChargingThrow = false; } diff --git a/Assets/Scripts/PlayerPlatformerController.cs b/Assets/Scripts/PlayerPlatformerController.cs index 4609c84..cf54920 100644 --- a/Assets/Scripts/PlayerPlatformerController.cs +++ b/Assets/Scripts/PlayerPlatformerController.cs @@ -205,10 +205,22 @@ public class PlayerPlatformerController : MonoBehaviour for (var i = 0; i < hits.Length; i++) { var hit = hits[i]; - if (hit != null && hit != bodyCollider) + if (hit == null || hit == bodyCollider || hit.isTrigger) { - return true; + continue; } + + if (hit.GetComponent() != null) + { + continue; + } + + if (hit.GetComponent() != null) + { + continue; + } + + return true; } return false; diff --git a/Assets/Scripts/TrickController.cs b/Assets/Scripts/TrickController.cs index f1775d2..bf9496f 100644 --- a/Assets/Scripts/TrickController.cs +++ b/Assets/Scripts/TrickController.cs @@ -25,14 +25,20 @@ public class TrickController : MonoBehaviour [SerializeField] private float wanderWeight = 0.4f; [SerializeField] private int maxTricks = 50; [SerializeField] private float jumpImpulse = 6f; + [SerializeField] private float jumpImpulseVariance = 0.25f; [SerializeField] private float jumpCooldown = 1f; [SerializeField] private float jumpChancePerSecond = 0.5f; + [SerializeField] private float jumpArcChance = 0.5f; + [SerializeField] private float jumpArcHorizontalImpulse = 2f; [SerializeField] private LayerMask groundMask = ~0; [SerializeField] private float groundCheckDistance = 0.05f; [SerializeField] private float despawnMinX = -12f; [SerializeField] private float despawnMaxX = 12f; [SerializeField] private float despawnMinY = -10f; + [SerializeField] private float despawnMaxY = 20f; [SerializeField] private float throwControlLockTime = 0.35f; + [SerializeField] private float wallCheckDistance = 0.1f; + [SerializeField] private float wallAvoidDuration = 0.6f; private Rigidbody2D body; private Transform target; @@ -44,6 +50,10 @@ public class TrickController : MonoBehaviour private float desiredXVelocity; private float nextJumpTime; private float movementLockUntil; + private readonly RaycastHit2D[] groundHits = new RaycastHit2D[4]; + private readonly RaycastHit2D[] wallHits = new RaycastHit2D[4]; + private float wallAvoidUntil; + private float wallAvoidDirection; private void Awake() { @@ -79,7 +89,7 @@ public class TrickController : MonoBehaviour } var position = transform.position; - if (position.x < despawnMinX || position.x > despawnMaxX || position.y < despawnMinY) + if (position.x < despawnMinX || position.x > despawnMaxX || position.y < despawnMinY || position.y > despawnMaxY) { Destroy(gameObject); return; @@ -128,9 +138,6 @@ public class TrickController : MonoBehaviour if (!IsGrounded()) { - var airborne = body.linearVelocity; - airborne.x = 0f; - body.linearVelocity = airborne; return; } @@ -156,6 +163,18 @@ public class TrickController : MonoBehaviour desiredX = wanderDirection.x * 0.2f; } + var wallDirection = GetWallAvoidDirection(desiredX); + if (wallDirection != 0f) + { + wallAvoidDirection = wallDirection; + wallAvoidUntil = Time.time + wallAvoidDuration; + } + + if (Time.time < wallAvoidUntil && Mathf.Abs(wallAvoidDirection) > 0.01f) + { + desiredX = wallAvoidDirection; + } + desiredVelocity = new Vector2(Mathf.Clamp(desiredX, -1f, 1f) * moveSpeed, 0f); var velocity = body.linearVelocity; @@ -311,6 +330,11 @@ public class TrickController : MonoBehaviour return; } + if (body.linearVelocity.y > 0.01f) + { + return; + } + var chance = jumpChancePerSecond * Time.fixedDeltaTime; if (Random.value > chance) { @@ -326,7 +350,17 @@ public class TrickController : MonoBehaviour } velocity.x = jumpDir * moveSpeed; body.linearVelocity = velocity; - body.AddForce(Vector2.up * jumpImpulse, ForceMode2D.Impulse); + + var minImpulse = Mathf.Max(0f, jumpImpulse * (1f - jumpImpulseVariance)); + var maxImpulse = Mathf.Max(minImpulse, jumpImpulse * (1f + jumpImpulseVariance)); + var jumpImpulseActual = Random.Range(minImpulse, maxImpulse); + body.AddForce(Vector2.up * jumpImpulseActual, ForceMode2D.Impulse); + + if (Random.value < jumpArcChance && jumpArcHorizontalImpulse > 0f) + { + var arcDir = Random.value < 0.5f ? -1f : 1f; + body.AddForce(Vector2.right * arcDir * jumpArcHorizontalImpulse, ForceMode2D.Impulse); + } nextJumpTime = Time.time + jumpCooldown; } @@ -338,22 +372,78 @@ public class TrickController : MonoBehaviour return false; } - var bounds = collider.bounds; - var checkSize = new Vector2(bounds.size.x * 0.9f, groundCheckDistance * 2f); - var checkCenter = new Vector2(bounds.center.x, bounds.min.y - groundCheckDistance); - var hits = Physics2D.OverlapBoxAll(checkCenter, checkSize, 0f, groundMask); - for (var i = 0; i < hits.Length; i++) + var filter = new ContactFilter2D(); + filter.SetLayerMask(groundMask); + filter.useTriggers = false; + + var hitCount = collider.Cast(Vector2.down, filter, groundHits, groundCheckDistance); + for (var i = 0; i < hitCount; i++) { - var hit = hits[i]; - if (hit != null && hit != collider) + var hitCollider = groundHits[i].collider; + if (hitCollider == null || hitCollider == collider) { - return true; + continue; } + + if (hitCollider.GetComponent() != null) + { + continue; + } + + if (hitCollider.GetComponent() != null) + { + continue; + } + + return true; } return false; } + private float GetWallAvoidDirection(float desiredX) + { + if (Mathf.Abs(desiredX) < 0.01f) + { + return 0f; + } + + var collider = GetComponent(); + if (collider == null) + { + return 0f; + } + + var filter = new ContactFilter2D(); + filter.SetLayerMask(groundMask); + filter.useTriggers = false; + + var dir = Mathf.Sign(desiredX); + var hitCount = collider.Cast(Vector2.right * dir, filter, wallHits, wallCheckDistance); + for (var i = 0; i < hitCount; i++) + { + var hitCollider = wallHits[i].collider; + if (hitCollider == null || hitCollider == collider) + { + continue; + } + + if (hitCollider.GetComponent() != null) + { + continue; + } + + if (hitCollider.GetComponent() != null) + { + continue; + } + + return -dir; + } + + return 0f; + } + public void SetCarried(bool carried) {