feat: Implement NavMesh pathfinding and Deep Social visuals
- Phase 20-F: NavMesh Integration - Added 'com.unity.ai.navigation' package - Implemented Runtime NavMesh Baking in EnvironmentManager - Added NavMeshObstacle to environmental assets - Updated AgentVisual to use NavMeshAgent for movement - Implemented 'Instinctive Avoidance' via target offsetting - Phase 21: Social Interaction & Expressions - Added procedural Dance and Wave animations in AgentAnimator - Implemented 'Dance Party' triggering logic in engine.py and AgentVisual - Added social relationship syncing (Backend -> Frontend) - Implemented proximity-based social greetings (Heart emote + Wave) - Updated Models.cs to support relationship data parsing
This commit is contained in:
@@ -28,6 +28,8 @@ namespace TheIsland
|
||||
private Vector3 _currentVelocity;
|
||||
private float _velocityPercentage; // 0 to 1
|
||||
private bool _isMoving;
|
||||
private bool _isDancing; // Phase 21
|
||||
private bool _isWaving; // Phase 21
|
||||
private float _jiggleOffset;
|
||||
private float _jiggleVelocity;
|
||||
|
||||
@@ -112,6 +114,12 @@ namespace TheIsland
|
||||
{
|
||||
AnimateIdle();
|
||||
}
|
||||
|
||||
// Phase 21: Override for Dance/Wave
|
||||
if (_isDancing) AnimateDance();
|
||||
if (_isWaving) AnimateWave();
|
||||
|
||||
// Smoothly apply transforms
|
||||
|
||||
// Smoothly apply transforms
|
||||
float lerpSpeed = 12f;
|
||||
@@ -156,6 +164,47 @@ namespace TheIsland
|
||||
_targetScale = new Vector3(_originalScale.x * squash, _originalScale.y * stretch, _originalScale.z);
|
||||
}
|
||||
|
||||
// Phase 21: Social Actions
|
||||
public void SetDancing(bool dancing)
|
||||
{
|
||||
_isDancing = dancing;
|
||||
}
|
||||
|
||||
public void SetWaving(bool waving)
|
||||
{
|
||||
_isWaving = waving;
|
||||
}
|
||||
|
||||
private void AnimateDance()
|
||||
{
|
||||
// Fast rhythmic bounce (130 BPM style)
|
||||
float cycle = Time.time * 15f;
|
||||
float danceBounce = Mathf.Abs(Mathf.Sin(cycle)) * 0.15f;
|
||||
float danceTilt = Mathf.Sin(cycle * 0.5f) * 10f;
|
||||
|
||||
// Apply dance transforms
|
||||
_targetLocalPos = new Vector3(0, danceBounce, 0);
|
||||
_targetLocalRot = Quaternion.Euler(0, 0, danceTilt);
|
||||
|
||||
// Strong squash/stretch on the beat
|
||||
float stretch = 1f + danceBounce * 1.5f;
|
||||
float squash = 1f / stretch;
|
||||
_targetScale = new Vector3(_originalScale.x * squash, _originalScale.y * stretch, _originalScale.z);
|
||||
}
|
||||
|
||||
private void AnimateWave()
|
||||
{
|
||||
// Fast waving rotation
|
||||
float waveCycle = Time.time * 20f;
|
||||
float waveTilt = Mathf.Sin(waveCycle) * 20f; // Exaggerated tilt
|
||||
|
||||
_targetLocalRot = Quaternion.Euler(0, 0, waveTilt);
|
||||
|
||||
// Slight jump for excitement
|
||||
float jumpCurve = Mathf.Abs(Mathf.Sin(Time.time * 5f)) * 0.1f;
|
||||
_targetLocalPos = new Vector3(0, jumpCurve, 0);
|
||||
}
|
||||
|
||||
private IEnumerator ActionPulseRoutine(float duration, float targetScaleY)
|
||||
{
|
||||
float elapsed = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.AI.Navigation;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using TheIsland.Core;
|
||||
using TheIsland.Network;
|
||||
using TheIsland.Models;
|
||||
@@ -76,6 +78,9 @@ namespace TheIsland.Visual
|
||||
private Color _targetSkyTop, _targetSkyBottom;
|
||||
private Color _currentSkyTop, _currentSkyBottom;
|
||||
private List<Transform> _palmTrees = new List<Transform>();
|
||||
|
||||
// Phase 20-F: NavMesh Surface
|
||||
private NavMeshSurface _navMeshSurface;
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
@@ -115,6 +120,12 @@ namespace TheIsland.Visual
|
||||
{
|
||||
new GameObject("VisualEffectsManager").AddComponent<VisualEffectsManager>();
|
||||
}
|
||||
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// Phase 20-F: Build NavMesh at Runtime
|
||||
BuildRuntimeNavMesh();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -203,6 +214,23 @@ namespace TheIsland.Visual
|
||||
CreateClouds();
|
||||
}
|
||||
|
||||
private void BuildRuntimeNavMesh()
|
||||
{
|
||||
// Ensure we have a NavMeshSurface component
|
||||
if (_navMeshSurface == null)
|
||||
{
|
||||
_navMeshSurface = gameObject.AddComponent<NavMeshSurface>();
|
||||
}
|
||||
|
||||
// Configure for 2D/2.5D agent
|
||||
_navMeshSurface.useGeometry = NavMeshCollectGeometry.PhysicsColliders;
|
||||
_navMeshSurface.collectObjects = CollectObjects.Children; // Collect ground and obstacles
|
||||
|
||||
// Rebuild
|
||||
_navMeshSurface.BuildNavMesh();
|
||||
Debug.Log("[EnvironmentManager] Runtime NavMesh Built.");
|
||||
}
|
||||
|
||||
private void CreateSky()
|
||||
{
|
||||
// Create a gradient sky using a camera background shader
|
||||
@@ -219,7 +247,7 @@ namespace TheIsland.Visual
|
||||
Destroy(skyObj.GetComponent<Collider>());
|
||||
|
||||
// Create gradient material
|
||||
_skyMaterial = CreateGradientMaterial();
|
||||
_skyMaterial = CreateGradientTextureMaterial();
|
||||
skyObj.GetComponent<Renderer>().material = _skyMaterial;
|
||||
skyObj.GetComponent<Renderer>().sortingOrder = -100;
|
||||
|
||||
@@ -449,6 +477,13 @@ namespace TheIsland.Visual
|
||||
float spriteHeightUnits = trunkRenderer.sprite.rect.height / trunkRenderer.sprite.pixelsPerUnit;
|
||||
float normScale = scale / spriteHeightUnits;
|
||||
trunkSprite.transform.localScale = new Vector3(normScale, normScale, 1);
|
||||
|
||||
// Phase 20-F: NavMesh Obstacle
|
||||
var obstacle = treeObj.AddComponent<NavMeshObstacle>();
|
||||
obstacle.shape = NavMeshObstacleShape.Box;
|
||||
obstacle.center = new Vector3(0, 0.5f * scale, 0); // Center at base, scaled height
|
||||
obstacle.size = new Vector3(0.5f * normScale, 1f * scale, 0.5f * normScale); // Trunk size, scaled
|
||||
obstacle.carving = true; // Force agents to walk around
|
||||
}
|
||||
|
||||
private Texture2D _envTexture;
|
||||
@@ -630,6 +665,13 @@ namespace TheIsland.Visual
|
||||
float spriteWidthUnits = rockRenderer.sprite.rect.width / rockRenderer.sprite.pixelsPerUnit;
|
||||
float normScale = scale / spriteWidthUnits;
|
||||
rockObj.transform.localScale = Vector3.one * normScale;
|
||||
|
||||
// Phase 20-F: NavMesh Obstacle
|
||||
var obstacle = rockObj.AddComponent<NavMeshObstacle>();
|
||||
obstacle.shape = NavMeshObstacleShape.Box;
|
||||
obstacle.center = new Vector3(0, 0.25f * scale, 0); // Center at base, scaled height
|
||||
obstacle.size = new Vector3(0.8f * normScale, 0.5f * scale, 0.8f * normScale); // Rock size, scaled
|
||||
obstacle.carving = true; // Force agents to walk around
|
||||
}
|
||||
|
||||
private Sprite CreateRockSprite()
|
||||
|
||||
Reference in New Issue
Block a user