using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; namespace Rokojori { [Tool] [GlobalClass] public partial class MultiRayCaster:Caster { public enum UpdateMode { Process, Physics_Process } [Export] public float rayLength = 10; [Export] public int maxHits = 3; List collisions = new List(); int numCollisions = 0; [Export] public Vector3 to; [Export] public UpdateMode updateMode = UpdateMode.Physics_Process; [Export] public Action beforeProcess; [Export] public Action afterProcess; [ExportGroup( "Debugging")] [Export] public Node collider; [Export] public bool printColliderNames = false; PhysicsRayQueryParameters3D rayParameters = new PhysicsRayQueryParameters3D(); public override void _PhysicsProcess( double delta ) { if ( UpdateMode.Physics_Process != updateMode ) { return; } Update( delta ); } public override void _Process( double delta ) { if ( UpdateMode.Process != updateMode ) { return; } Update( delta ); } [Export] public bool runInEditor = false; void Update( double delta ) { if ( Engine.IsEditorHint() && ! runInEditor ) { return; } Action.Trigger( beforeProcess ); ResolveCollisions(); SortCollisions(); var nextCollider = NumColliders() == 0 ? null : GetCollider( 0 ); if ( nextCollider != collider ) { collider = nextCollider; if ( printColliderNames ) { this.LogInfo( "New Collider:", HierarchyName.Of( collider ) ); } } Action.Trigger( afterProcess ); } CollisionData GetCollisionData( int i ) { while ( collisions.Count <= i ) { collisions.Add( new CollisionData() ); } return collisions[ i ]; } void ResolveCollisions() { var physics = GetWorld3D().DirectSpaceState; var excludes = new Array(); var from = GlobalPosition; var to = from + this.GlobalForward().Normalized() * rayLength; this.to = to; rayParameters.From = from; rayParameters.To = to; numCollisions = 0; for ( int i = 0; i < maxHits; i++ ) { rayParameters.Exclude = excludes; var collisionData = GetCollisionData( numCollisions ); collisionData.Get( rayParameters, physics ); if ( ! collisionData.hasCollision || this.DistanceTo( collisionData.position ) > rayLength ) { return; } excludes.Add( collisionData.rid ); if ( IsSelected( collisionData ) ) { numCollisions ++; } } } } }