using UnityEngine; using System.Collections.Generic; public class CuttingSystem : MonoBehaviour { [Header("切割系统参数")] public float snapDistance = 0.3f; public float detachDistance = 1.0f; public float directionSwitchCooldown = 0.2f; private CutLineManager cutLineManager; public float tractionSpeed = 2f; [Header("测试")] public SpriteRenderer TargetspriteRenderer; private GearController gearController; private Camera mainCamera; private int currentEdgeIndex = 0; private int tractionDirection = 1; private float directionSwitchTimer = 0f; private enum State { Follow, Traction } private State currentState = State.Follow; private List edgePoints; private List originalEdgePoints; private void Start() { mainCamera = Camera.main; gearController = GetComponentInChildren(); cutLineManager = GetComponentInChildren(); edgePoints = new List(); originalEdgePoints = new List(); if (TargetspriteRenderer != null) { InitializeCutting(TargetspriteRenderer); } else { Debug.LogError("TargetspriteRenderer is null!"); } } private void Update() { UpdateCutting(); } public void InitializeCutting(SpriteRenderer targetSprite, float edgePointsScale = 1.2f) { if (targetSprite == null) return; LoadEdgePointsFromSprite(targetSprite, edgePointsScale); Debug.Log($"InitializeCutting: edgePoints count = {edgePoints.Count}"); } public void UpdateCutting() { Vector2 mouseWorldPos = mainCamera.ScreenToWorldPoint(Input.mousePosition); if (Input.GetMouseButton(0)) { gearController.SetRotation(true); } else { gearController.SetRotation(false); } switch (currentState) { case State.Follow: UpdateFollowState(mouseWorldPos); break; case State.Traction: UpdateTractionState(mouseWorldPos); break; } } private void LoadEdgePointsFromSprite(SpriteRenderer targetSprite, float edgePointsScale) { var shapePoints = CuttingUtils.GetSpritePhysicsShapePoints(targetSprite); if (shapePoints == null) return; var (scaledPoints, originalPoints) = CuttingUtils.ProcessEdgePoints(shapePoints, targetSprite, edgePointsScale); if (scaledPoints == null) return; edgePoints = scaledPoints; originalEdgePoints = originalPoints; Debug.Log($"LoadEdgePointsFromSprite: edgePoints count = {edgePoints.Count}"); } private void UpdateFollowState(Vector2 mousePos) { gearController.transform.position = mousePos; int nearestIndex = CuttingUtils.FindNearestEdgePointIndex(mousePos, edgePoints, out float dist); Debug.Log($"Distance to nearest point: {dist}, Snap distance: {snapDistance}"); if (dist < snapDistance) { currentEdgeIndex = nearestIndex; Vector2 prev = edgePoints[CuttingUtils.WrapIndex(currentEdgeIndex - 1, edgePoints.Count)]; Vector2 next = edgePoints[CuttingUtils.WrapIndex(currentEdgeIndex + 1, edgePoints.Count)]; float distToPrev = Vector2.Distance(mousePos, prev); float distToNext = Vector2.Distance(mousePos, next); tractionDirection = (distToNext < distToPrev) ? 1 : -1; gearController.transform.position = edgePoints[currentEdgeIndex]; currentState = State.Traction; Debug.Log("Switched to Traction state"); } } private void UpdateTractionState(Vector2 mousePos) { Vector2 gearPos = transform.position; if (Vector2.Distance(mousePos, gearPos) > detachDistance) { currentState = State.Follow; cutLineManager.EndCutting(); return; } if (!Input.GetMouseButton(0)) { cutLineManager.EndCutting(); return; } if (!cutLineManager.IsCutting) { cutLineManager.StartCutting(); } int nextIndex = CuttingUtils.WrapIndex(currentEdgeIndex + tractionDirection, edgePoints.Count); Vector2 from = edgePoints[currentEdgeIndex]; Vector2 to = edgePoints[nextIndex]; Vector2 forward = (to - from).normalized; Vector2 toMouse = (mousePos - from).normalized; float angle = Vector2.SignedAngle(forward, toMouse); if (Mathf.Abs(angle) > 120f) { directionSwitchTimer += Time.deltaTime; if (directionSwitchTimer > directionSwitchCooldown) { tractionDirection *= -1; directionSwitchTimer = 0f; nextIndex = CuttingUtils.WrapIndex(currentEdgeIndex + tractionDirection, edgePoints.Count); from = edgePoints[currentEdgeIndex]; to = edgePoints[nextIndex]; forward = (to - from).normalized; } } else { directionSwitchTimer = 0f; } Vector2 targetPoint = CuttingUtils.GetClosestPointOnSegment(from, to, mousePos); Vector2 moveDir = (targetPoint - gearPos); float distance = moveDir.magnitude; float maxStep = tractionSpeed * Time.deltaTime; if (distance <= maxStep) { gearController.transform.position = targetPoint; if (Vector2.Distance(targetPoint, to) < 0.01f) { currentEdgeIndex = nextIndex; } } else { gearController.transform.position += (Vector3)(moveDir.normalized * maxStep); } Vector2 originalFrom = originalEdgePoints[currentEdgeIndex]; Vector2 originalTo = originalEdgePoints[nextIndex]; Vector2 originalTargetPoint = CuttingUtils.GetClosestPointOnSegment(originalFrom, originalTo, transform.position); Vector3 noisyPoint = originalTargetPoint; noisyPoint.x += Random.Range(-cutLineManager.noiseAmount, cutLineManager.noiseAmount); noisyPoint.y += Random.Range(-cutLineManager.noiseAmount, cutLineManager.noiseAmount); cutLineManager.AddCutPoint(noisyPoint); } }