修改水
This commit is contained in:
@@ -1,138 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Obi.Samples
|
||||
{
|
||||
[RequireComponent(typeof(ObiSolver))]
|
||||
public class TangledRopesGameController : MonoBehaviour
|
||||
{
|
||||
public TangledPegSlot[] pegSlots;
|
||||
public float pegHoverHeight = 1;
|
||||
public float maxPegDistanceFromSlot = 1.5f;
|
||||
public int framesWithoutContactsToWin = 30;
|
||||
public UnityEvent onFinish = new UnityEvent();
|
||||
|
||||
private TangledPeg selectedPeg;
|
||||
private Plane floor = new Plane(Vector3.up, 0);
|
||||
private int framesSinceLastContact = 0;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
GetComponent<ObiSolver>().OnParticleCollision += Solver_OnParticleCollision;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
GetComponent<ObiSolver>().OnParticleCollision -= Solver_OnParticleCollision;
|
||||
}
|
||||
|
||||
private TangledPegSlot FindCandidateSlot(TangledPeg peg)
|
||||
{
|
||||
// Go over all slots, find the closest one to the peg that's closer than
|
||||
// maxPegDistanceFromSlot:
|
||||
|
||||
TangledPegSlot closest = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
|
||||
foreach (TangledPegSlot slot in pegSlots)
|
||||
{
|
||||
// reset slot color, to make sure it looks normal if it's not a candidate for our peg.
|
||||
slot.ResetColor();
|
||||
|
||||
// ignore occupied slots:
|
||||
if (slot.currentPeg != null)
|
||||
continue;
|
||||
|
||||
Vector3 slotOnFloor = floor.ClosestPointOnPlane(slot.transform.position);
|
||||
Vector3 pegOnFloor = floor.ClosestPointOnPlane(peg.transform.position);
|
||||
|
||||
float distance = Vector3.Distance(slotOnFloor, pegOnFloor);
|
||||
if (distance < closestDistance && distance < maxPegDistanceFromSlot)
|
||||
{
|
||||
closest = slot;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
|
||||
// User clicks, cast a ray towards the floor, see if it hits any peg.
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
if (Physics.Raycast(ray, out RaycastHit hit))
|
||||
{
|
||||
// if the ray hit a peg, store it as the selected peg and lift it off from its current slot.
|
||||
if (hit.transform.TryGetComponent(out TangledPeg peg) && peg.currentSlot != null)
|
||||
{
|
||||
selectedPeg = peg;
|
||||
selectedPeg.UndockFromCurrentSlot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedPeg != null)
|
||||
{
|
||||
// Make selected peg follow the mouse cursor:
|
||||
if (floor.Raycast(ray, out float enter))
|
||||
selectedPeg.MoveTowards(ray.GetPoint(enter) + Vector3.up * pegHoverHeight);
|
||||
|
||||
// Try to find a suitable slot to drop the peg:
|
||||
TangledPegSlot closest = FindCandidateSlot(selectedPeg);
|
||||
|
||||
// If we found a candidate slot, tint it to give the player some visual feedback:
|
||||
if (closest != null)
|
||||
closest.Tint();
|
||||
|
||||
// Drop selected peg:
|
||||
if (Input.GetMouseButtonUp(0))
|
||||
{
|
||||
// If we could find a free slot nearby, connect to it:
|
||||
if (closest != null)
|
||||
{
|
||||
selectedPeg.currentSlot = null;
|
||||
selectedPeg.DockInSlot(closest);
|
||||
closest.ResetColor();
|
||||
}
|
||||
else // If we couldn't find one or if it's too far, return to current slot.
|
||||
{
|
||||
selectedPeg.DockInSlot(selectedPeg.currentSlot);
|
||||
}
|
||||
|
||||
selectedPeg = null;
|
||||
}
|
||||
}
|
||||
|
||||
// If all ropes have been contact-free for a certain amount of frames, trigger finish event.
|
||||
if (framesSinceLastContact >= framesWithoutContactsToWin && onFinish != null)
|
||||
onFinish.Invoke();
|
||||
|
||||
}
|
||||
|
||||
private void Solver_OnParticleCollision(ObiSolver s, ObiNativeContactList e)
|
||||
{
|
||||
// Count contacts between different ropes (that is, exclude self-contacts):
|
||||
int contactsBetweenRopes = 0;
|
||||
|
||||
for (int i = 0; i < e.count; ++i)
|
||||
{
|
||||
var ropeA = s.particleToActor[s.simplices[e[i].bodyA]].actor;
|
||||
var ropeB = s.particleToActor[s.simplices[e[i].bodyB]].actor;
|
||||
|
||||
if (ropeA != ropeB)
|
||||
contactsBetweenRopes++;
|
||||
}
|
||||
|
||||
// If there's no contacts, bump the amount of frames we've been contact-free.
|
||||
// Otherwise reset the amount of frames to zero.
|
||||
if (contactsBetweenRopes == 0)
|
||||
framesSinceLastContact++;
|
||||
else
|
||||
framesSinceLastContact = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user