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)
{