射线及其碰撞检测 [代码清单6-7]

本文详细介绍了使用Unity3D进行游戏开发时,如何通过射线及碰撞检测实现目标定位与交互。重点阐述了创建摄像机到鼠标射线的方法,并通过Physics.Raycast函数判断射线是否击中游戏对象,进而实现打靶效果。

Unity3D游戏开发 宣雨松 著。射线及其碰撞检测

using UnityEngine;
using System.Collections;

public class Script_06_09 : MonoBehaviour {
    // 靶心贴图
    public Texture texture;
    // 提示信息
    private string info;
	
	// Update is called once per frame
	void Update () {
        // 创建摄像机到鼠标的射线
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        RaycastHit hit;
        // 判断该射线是否打中游戏对象
        if (Physics.Raycast(ray, out hit))
        {
            info = "打中靶心";
        }
        else
            info = "未打中靶心";	
	}

    void OnGUI() { 
        // 计算中心贴图的坐标
        Rect rect = new Rect(Input.mousePosition.x - (texture.width >> 1), Screen.height - Input.mousePosition.y - (texture.height >> 1),
            texture.width, texture.height);

        // 绘制准心贴图
        GUI.DrawTexture(rect, texture);
        // 输入打靶子的信息
        GUILayout.Label(info + ", 打中的坐标为: " + Input.mousePosition);
    }
}


using FishNet.Object.Synchronizing; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace ForestRush { [FRBehaviour(1)] public class FRPushTrap : FRTileGameObjectBase, ICellShapeHandler, ISpawnHandler, ISelectMapObjHandler, IPlayHandler, ITriggerEnterHandler { [SerializeField] private BoxCollider2D m_collider2D; [SerializeField] private SpriteMask m_spriteMask; [SerializeField] private BoxCollider2D m_detectArea; [SerializeField] private BoxCollider2D m_Restrictcollider; [FRUGC(typeof(int), "陷阱长度", minValue: 0, maxValue: 9)] private int leftColumnCount = 0; [FRUGC(typeof(float), "移动速度", minValue: 5, maxValue: 15)] private float moveSpeed = 5f; [FRUGC(typeof(float), "推出时间", minValue: 2, maxValue: 5)] private float coldTime = 3f; [Tooltip("玩家射线长度")] [SerializeField] private float playerRayLength = 1.5f; [Tooltip("玩家射线检测层")] [SerializeField] private LayerMask wallLayer; [Tooltip("检测层(玩家层)")] [SerializeField] private LayerMask playerLayer; [Tooltip("检测间隔时间")] [SerializeField] private float checkInterval = 0.1f; [Tooltip("挤压最小厚度(玩家和障碍物的最小距离)")] [SerializeField] private float minSqueezeThickness = 1f; [Tooltip("速度判断阈值")] [SerializeField] private float speedThreshold = 0.5f; [SerializeField] private GameObject leftColumnPrefab; [SerializeField] private GameObject PushDirection; [SerializeField] private Transform leftColumnsContainer; [SerializeField] private Rigidbody2D m_leftRigidboyd2d; private List<GameObject> generatedLeftColumns = new List<GameObject>(); private Vector2 originalColliderSize; private Vector2 originalColliderOffset; private Vector3 originalPosition; private bool IsPushing = false; private bool backpushing = false; private float stoppedTime = 0f; //private Coroutine crushDetectionCoroutine; protected void Awake() { if (leftColumnsContainer == null) { leftColumnsContainer = transform.Find("LeftColumnsContainer"); } if (m_collider2D != null) { originalColliderSize = m_collider2D.size; originalColliderOffset = m_collider2D.offset; } if (playerLayer.value == 0) { playerLayer = LayerMask.GetMask("Player"); } if (wallLayer.value == 0) { wallLayer = LayerMask.GetMask("Default"); } } public void OnNetworkTriggerEnter(FRTriggerBodyInfo2D info) { if (info.PhysicsNetworkBehaviour != null && info.PhysicsNetworkBehaviour.TryGetComponent<FRPlayerController>(out var playerController)) { if (m_leftRigidboyd2d.transform.position.x - 0.5f <= originalPosition.x) { IsPushing = true; Debug.Log($"开始推动,左侧列数: {leftColumnCount}"); //StartCoroutine(CrushDetectionRoutine()); } } } private void OnExit2D(FRCollisionBody2D collision) { if (collision.PhysicsNetworkBehaviour != null) { FRPlayerController player = collision.PhysicsNetworkBehaviour.GetComponent<FRPlayerController>(); if (player != null) { player.ApplyPlatformMove(Vector2.zero); } } } private void OnEnter2D(FRCollisionBody2D collision) { if (collision.Timing != CollisionTiming.Regular) return; if (IsPushing) { // 先判断碰撞的是什么 if (collision.PhysicsNetworkBehaviour != null) { // 检查是否是玩家 FRPlayerController player = collision.PhysicsNetworkBehaviour.GetComponent<FRPlayerController>(); if (player != null) { Debug.Log($"碰撞检测到玩家: {player.name}"); // 如果是玩家,进行玩家挤压检测 if (CheckPlayerCrush(player)) { OnPlayerCrushed(player); } } // 检查是否是其他刚体 else { Rigidbody2D otherRigid = collision.PhysicsNetworkBehaviour.GetComponent<Rigidbody2D>(); if (otherRigid != null) { Debug.Log($"碰撞检测到刚体: {otherRigid.name}"); // 如果不是玩家,进行刚体挤压检测 if (CheckRigidbodyCrush(otherRigid)) { // 刚体被挤压,检查后面是否有玩家 CheckPlayerBehindRigidbody(otherRigid); } } } } } } private void OnStay2D(FRCollisionBody2D collision) { if (collision.Timing != CollisionTiming.Regular) return; if (IsPushing) { if (collision.PhysicsNetworkBehaviour != null) { // 检查是否是玩家 FRPlayerController player = collision.PhysicsNetworkBehaviour.GetComponent<FRPlayerController>(); if (player != null) { if (player.transform.position.y > m_leftRigidboyd2d.transform.position.y) { player.ApplyPlatformMove(m_leftRigidboyd2d.velocity); } // 持续检测玩家是否被挤压 if (CheckPlayerCrush(player)) { OnPlayerCrushed(player); } } // 检查是否是其他刚体 else { Rigidbody2D otherRigid = collision.PhysicsNetworkBehaviour.GetComponent<Rigidbody2D>(); if (otherRigid != null) { // 持续检测刚体是否被挤压 if (CheckRigidbodyCrush(otherRigid)) { CheckPlayerBehindRigidbody(otherRigid); } } } } } } #region 主要检测逻辑 /// <summary> /// 检测玩家是否被挤压 /// </summary> private bool CheckPlayerCrush(FRPlayerController player) { if (player == null || m_collider2D == null) return false; // 1. 检查玩家是否在陷阱和墙之间 bool isTrapped = CheckPlayerTrapped(player); // 2. 检查陷阱状态 if (isTrapped) { bool isTrapStopped = IsTrapEffectivelyStopped(); bool isNotAtMaxDistance = !IsAtMaxDistance(); // 和原来一样的判断条件 if (isNotAtMaxDistance && isTrapStopped) { return true; } } return false; } /// <summary> /// 检测刚体是否被挤压 /// </summary> private bool CheckRigidbodyCrush(Rigidbody2D otherRigid) { if (otherRigid == null || m_collider2D == null) return false; // 1. 检查刚体是否在陷阱和墙之间 bool isTrapped = CheckRigidbodyTrapped(otherRigid); // 2. 检查陷阱状态 if (isTrapped) { bool isTrapStopped = IsTrapEffectivelyStopped(); bool isNotAtMaxDistance = !IsAtMaxDistance(); // 和原来一样的判断条件 if (isNotAtMaxDistance && isTrapStopped) { return true; } } return false; } #endregion #region 核心射线检测逻辑 - 修改版 /// <summary> /// 检查玩家是否被夹在陷阱和墙之间 /// </summary> private bool CheckPlayerTrapped(FRPlayerController player) { if (player == null || m_collider2D == null) return false; Vector2 playerPosition = player.transform.position; Vector2 pushDirection = GetPushDirection(); Vector2 crushDirection = pushDirection; // 挤压方向 // 从玩家头和脚位置向挤压方向发射射线 Vector2[] rayStartPositions = new Vector2[] { playerPosition + Vector2.up * 0.5f, // 头 playerPosition + Vector2.down * 0.5f, // 脚 playerPosition, // 中间 }; foreach (Vector2 startPos in rayStartPositions) { // 递归检测,直到找到墙 if (RecursiveRaycastToWall(startPos, crushDirection, player.transform)) { // 检查反方向是否能打到陷阱 if (CheckReverseRayToTrap(startPos, -crushDirection, player.transform)) { return true; } } } return false; } /// <summary> /// 检查刚体是否被夹在陷阱和墙之间 /// </summary> private bool CheckRigidbodyTrapped(Rigidbody2D otherRigid) { if (otherRigid == null || m_collider2D == null) return false; Vector2 rigidbodyPosition = otherRigid.position; Vector2 pushDirection = GetPushDirection(); Vector2 crushDirection = pushDirection; // 挤压方向 // 从刚体位置向挤压方向发射射线 Vector2[] rayStartPositions = new Vector2[] { rigidbodyPosition + Vector2.up * 0.2f, rigidbodyPosition + Vector2.down * 0.2f, rigidbodyPosition + Vector2.left * 0.2f, rigidbodyPosition + Vector2.right * 0.2f, rigidbodyPosition, }; foreach (Vector2 startPos in rayStartPositions) { // 递归检测,直到找到玩家或墙 if (RecursiveRaycastToPlayerOrWall(startPos, crushDirection, otherRigid.transform)) { // 检查反方向是否能打到陷阱 if (CheckReverseRayToTrap(startPos, -crushDirection, otherRigid.transform)) { return true; } } } return false; } /// <summary> /// 递归射线检测直到找到墙(从玩家位置开始) /// </summary> private bool RecursiveRaycastToWall(Vector2 startPos, Vector2 direction, Transform startTransform) { return RecursiveRaycastToWallInternal(startPos, direction, startTransform, 0, 10); } private bool RecursiveRaycastToWallInternal(Vector2 startPos, Vector2 direction, Transform startTransform, int depth, int maxDepth) { if (depth >= maxDepth) { Debug.LogWarning("达到最大递归深度"); return false; } // 发射射线,检测所有层 RaycastHit2D[] hits = Physics2D.RaycastAll(startPos, direction, playerRayLength * 2f, ~0); // 检测所有层 // 绘制调试射线 Debug.DrawRay(startPos, direction * playerRayLength * 2f, Color.red, checkInterval); // 按距离排序 System.Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance)); foreach (RaycastHit2D hit in hits) { if (hit.collider == null || hit.collider.isTrigger) continue; // 跳过起始物体自身 if (hit.collider.transform == startTransform || hit.collider.transform.IsChildOf(startTransform)) continue; // 检查是否是墙(Default层) if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Default")) { // 检查距离 float distanceToWall = hit.distance; bool isDistanceSmall = distanceToWall < minSqueezeThickness; if (isDistanceSmall) { Debug.Log($"找到墙,距离: {distanceToWall}"); return true; } return false; } // 跳过陷阱自身 if (hit.collider.transform.IsChildOf(transform)) continue; // 如果是其他物体(箱子等),继续递归 // 从物体的另一侧继续发射射线 Vector2 newStartPos = hit.point + direction * 0.05f; // 稍微偏移,避免自碰撞 // 绘制穿透射线的调试线 Debug.DrawRay(newStartPos, direction * (playerRayLength * 2f - hit.distance), Color.yellow, checkInterval); if (RecursiveRaycastToWallInternal(newStartPos, direction, hit.collider.transform, depth + 1, maxDepth)) { return true; } } return false; } /// <summary> /// 递归射线检测直到找到玩家或墙(从刚体位置开始) /// </summary> private bool RecursiveRaycastToPlayerOrWall(Vector2 startPos, Vector2 direction, Transform startTransform) { return RecursiveRaycastToPlayerOrWallInternal(startPos, direction, startTransform, 0, 10); } private bool RecursiveRaycastToPlayerOrWallInternal(Vector2 startPos, Vector2 direction, Transform startTransform, int depth, int maxDepth) { if (depth >= maxDepth) { Debug.LogWarning("达到最大递归深度"); return false; } // 发射射线,检测所有层 RaycastHit2D[] hits = Physics2D.RaycastAll(startPos, direction, playerRayLength * 2f, ~0); // 检测所有层 // 绘制调试射线 Debug.DrawRay(startPos, direction * playerRayLength * 2f, Color.blue, checkInterval); // 按距离排序 System.Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance)); foreach (RaycastHit2D hit in hits) { if (hit.collider == null || hit.collider.isTrigger) continue; // 跳过起始物体自身 if (hit.collider.transform == startTransform || hit.collider.transform.IsChildOf(startTransform)) continue; // 检查是否是玩家 FRPlayerController player = hit.collider.GetComponent<FRPlayerController>(); if (player != null) { Debug.Log($"找到玩家: {player.name}"); // 找到玩家后,从玩家位置继续检测直到墙 Vector2 playerPos = player.transform.position; Vector2[] playerRayStarts = new Vector2[] { playerPos + Vector2.up * 0.5f, playerPos + Vector2.down * 0.5f, playerPos, }; foreach (Vector2 playerStart in playerRayStarts) { // 从玩家位置向挤压方向发射射线 RaycastHit2D[] playerHits = Physics2D.RaycastAll(playerStart, direction, playerRayLength * 2f, ~0); // 绘制玩家位置的射线 Debug.DrawRay(playerStart, direction * playerRayLength * 2f, Color.magenta, checkInterval); System.Array.Sort(playerHits, (a, b) => a.distance.CompareTo(b.distance)); foreach (RaycastHit2D playerHit in playerHits) { if (playerHit.collider == null || playerHit.collider.isTrigger) continue; // 跳过玩家自身 if (playerHit.collider.transform == player.transform) continue; // 跳过陷阱 if (playerHit.collider.transform.IsChildOf(transform)) continue; // 检查是否是墙(Default层) if (playerHit.collider.gameObject.layer == LayerMask.NameToLayer("Default")) { float distanceToWall = playerHit.distance; bool isDistanceSmall = distanceToWall < minSqueezeThickness; if (isDistanceSmall) { Debug.Log($"玩家后面找到墙,距离: {distanceToWall}"); return true; } return false; } // 如果是其他物体(箱子等),继续从物体的另一侧发射射线 Vector2 newStartPos = playerHit.point + direction * 0.05f; // 递归检测 if (RecursiveRaycastToWallInternal(newStartPos, direction, playerHit.collider.transform, depth + 1, maxDepth)) { return true; } } } return false; } // 检查是否是墙(Default层) if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Default")) { float distanceToWall = hit.distance; bool isDistanceSmall = distanceToWall < minSqueezeThickness; if (isDistanceSmall) { Debug.Log($"直接找到墙,距离: {distanceToWall}"); return true; } return false; } // 跳过陷阱 if (hit.collider.transform.IsChildOf(transform)) continue; // 如果是其他物体(箱子等),继续递归 Vector2 newStartPos = hit.point + direction * 0.05f; if (RecursiveRaycastToPlayerOrWallInternal(newStartPos, direction, hit.collider.transform, depth + 1, maxDepth)) { return true; } } return false; } /// <summary> /// 检查反方向是否能打到陷阱 /// </summary> private bool CheckReverseRayToTrap(Vector2 startPos, Vector2 direction, Transform startTransform) { // 发射射线,检测所有层 RaycastHit2D[] hits = Physics2D.RaycastAll(startPos, direction, playerRayLength * 2f, ~0); // 绘制调试射线 Debug.DrawRay(startPos, direction * playerRayLength * 2f, Color.green, checkInterval); // 按距离排序 System.Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance)); foreach (RaycastHit2D hit in hits) { if (hit.collider == null || hit.collider.isTrigger) continue; // 跳过起始物体自身 if (hit.collider.transform == startTransform) continue; // 检查是否是陷阱 if (hit.collider.transform.IsChildOf(transform)) { Debug.Log($"反方向找到陷阱"); return true; } // 如果是墙,说明被挡住了,看不到陷阱 if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Default")) { return false; } // 如果是其他物体,继续检测(穿透物体) // 从物体的另一侧继续发射射线 Vector2 newStartPos = hit.point + direction * 0.05f; // 递归检查 return CheckReverseRayToTrap(newStartPos, direction, hit.collider.transform); } return false; } #endregion #region 辅助方法 /// <summary> /// 检查刚体后面是否有玩家 /// </summary> private void CheckPlayerBehindRigidbody(Rigidbody2D rigidbody) { if (rigidbody == null) return; Vector2 pushDirection = GetPushDirection(); Vector2 crushDirection = pushDirection; // 挤压方向 // 从刚体位置向挤压方向发射射线,检测是否有玩家 RaycastHit2D[] hits = Physics2D.RaycastAll( rigidbody.position, crushDirection, playerRayLength * 2f, // 更长距离,确保能穿透物体 ~0 // 检测所有层 ); foreach (RaycastHit2D hit in hits) { if (hit.collider == null || hit.collider.isTrigger) continue; FRPlayerController player = hit.collider.GetComponent<FRPlayerController>(); if (player != null) { // 玩家在刚体后面,检查玩家是否也被挤压 Debug.Log($"发现玩家 {player.name} 在刚体 {rigidbody.name} 后面"); // 检查玩家是否被挤压 if (CheckPlayerCrush(player)) { Debug.Log($"玩家 {player.name} 也被挤压"); OnPlayerCrushed(player); } } } } #endregion #region 物理和移动控制 private void FixedUpdate() { StartPushing(); BackPushing(); } private void StopPushing() { if (m_leftRigidboyd2d != null) { IsPushing = false; m_leftRigidboyd2d.velocity = Vector2.zero; stoppedTime = 0f; } } private void BackPushing() { if (backpushing) { float adjustedSpeed = moveSpeed / Mathf.Max(1, leftColumnCount * 0.5f + 1); float targetX = originalPosition.x; float currentX = m_leftRigidboyd2d.transform.position.x; // 检查是否还需要后退 if (currentX > targetX) { // 计算正确的方向:从当前位置指向目标位置 Vector2 targetPosition = new Vector2(targetX, m_leftRigidboyd2d.transform.position.y); Vector2 currentPosition = m_leftRigidboyd2d.transform.position; Vector2 moveDirection = (targetPosition - currentPosition).normalized; m_leftRigidboyd2d.velocity = moveDirection * adjustedSpeed; } else { // 到达或超过目标位置,停止移动 Debug.Log("到达原始位置,停止后退"); backpushing = false; StopPushing(); } } } private void StartPushing() { if (IsPushing) { float targetX = m_Restrictcollider.transform.position.x + leftColumnCount * 1 + 1; float currentX = m_leftRigidboyd2d.transform.position.x; if (currentX < targetX) { Vector2 moveDirection = GetPushDirection(); m_leftRigidboyd2d.velocity = moveDirection * moveSpeed; // 检查是否被卡住(撞到墙或静态物体) if (IsTrapEffectivelyStopped() && !IsAtMaxDistance()) { stoppedTime += Time.fixedDeltaTime; Debug.Log($"停止时间: {stoppedTime}"); if (stoppedTime >= coldTime) { backpushing = true; stoppedTime = 0f; } } else { // 正常移动时重置计时 stoppedTime = 0f; } } else { Debug.Log("到达限制位置,停止推动"); backpushing = true; stoppedTime = 0f; } } else { if (m_leftRigidboyd2d != null) { m_leftRigidboyd2d.velocity = Vector2.zero; } // 不在推动状态时重置计时 stoppedTime = 0f; } } private Vector2 GetPushDirection() { if (PushDirection != null) { Vector2 direction = PushDirection.transform.localPosition.normalized; direction.y = 0; direction.x = Mathf.Abs(direction.x) + 1; return direction; } return Vector2.right; } #endregion #region 判断条件方法(保持原样) private bool IsTrapEffectivelyStopped() { if (m_leftRigidboyd2d == null) return false; float currentSpeed = m_leftRigidboyd2d.velocity.magnitude; bool isStopped = currentSpeed < speedThreshold; return isStopped; } private bool IsAtMaxDistance() { float targetX = m_Restrictcollider.transform.position.x + leftColumnCount * 1 + 1; float currentX = m_leftRigidboyd2d.transform.position.x; float buffer = 0.2f; bool isAtMax = currentX >= targetX - buffer; return isAtMax; } private bool IsBehindObjectStopped(Collider2D behindCollider) { if (behindCollider == null) return true; Rigidbody2D rb = behindCollider.GetComponent<Rigidbody2D>(); if (rb == null) return true; if (rb.isKinematic) return true; float currentSpeed = rb.velocity.magnitude; bool isStopped = currentSpeed < speedThreshold; return isStopped; } private bool IsBehindObjectStatic(Collider2D behindCollider) { if (behindCollider == null) return true; Rigidbody2D rb = behindCollider.GetComponent<Rigidbody2D>(); bool hasRigidbody = rb != null; bool isStaticLayer = behindCollider.gameObject.layer == LayerMask.NameToLayer("Default"); bool isStatic = !hasRigidbody || (rb != null && rb.isKinematic) || isStaticLayer; return isStatic; } #endregion #region 玩家死亡处理 private void OnPlayerCrushed(FRPlayerController player) { if (player == null) return; if (player.PlayerAttributeComp.GetAttribute(AttributeEnum.IsDead, out bool isDead)) { if (!isDead) { player.SetOnDead(true, FRPlayerController.DeadReason.Crushed); if (m_leftRigidboyd2d != null) { backpushing = true; BackPushing(); stoppedTime = 0f; } return; } } } #endregion #region 陷阱生成和管理(保持原样) public int GetCurrentColumnCount() { if (leftColumnsContainer == null) return 0; int count = 0; foreach (Transform child in leftColumnsContainer) { if (child.gameObject.activeSelf) count++; } return count; } private void ClearGeneratedColumns() { foreach (GameObject column in generatedLeftColumns) { if (column != null) Destroy(column); } generatedLeftColumns.Clear(); } private void UpdateColliderBasedOnColumns() { if (m_collider2D == null) return; if (leftColumnCount <= 0) { m_collider2D.size = originalColliderSize; m_collider2D.offset = originalColliderOffset; return; } float columnWidth = 1f; float totalLeftWidth = leftColumnCount * columnWidth; float newWidth = originalColliderSize.x + totalLeftWidth; float offsetX = originalColliderOffset.x - (totalLeftWidth / 2f); m_collider2D.size = new Vector2(newWidth, originalColliderSize.y); m_collider2D.offset = new Vector2(offsetX, originalColliderOffset.y); } private void GenerateLeftColumns() { if (leftColumnCount == 0) return; if (leftColumnsContainer == null) { GameObject containerObj = new GameObject("LeftColumnsContainer"); leftColumnsContainer = containerObj.transform; leftColumnsContainer.SetParent(transform); leftColumnsContainer.localPosition = Vector3.zero; } if (leftColumnPrefab == null) { Debug.LogWarning("左侧列预制体未设置!"); return; } for (int i = 0; i < leftColumnCount; i++) { GameObject newColumn = Instantiate(leftColumnPrefab, leftColumnsContainer); newColumn.name = $"LeftColumn_{i}"; float columnWidth = -1f; newColumn.transform.localPosition = new Vector3(i * columnWidth, 0, 0); SpriteRenderer columnRenderer = newColumn.GetComponent<SpriteRenderer>(); if (columnRenderer != null) columnRenderer.sortingOrder = i; generatedLeftColumns.Add(newColumn); } UpdateColliderBasedOnColumns(); } #endregion #region 调试和可视化 private void OnDrawGizmos() { if (!Application.isPlaying || !IsPushing) return; Gizmos.color = Color.blue; Vector2 trapPosition = m_collider2D != null ? m_collider2D.bounds.center : m_leftRigidboyd2d.transform.position; Vector2 direction = GetPushDirection(); Gizmos.DrawRay(trapPosition, direction * 2f); Gizmos.color = Color.red; Gizmos.DrawRay(trapPosition, -direction * 2f); } #endregion #region 接口实现 public IEnumerable<Vector2Int> GetLocalCells() { yield return new Vector2Int(0, 0); yield return new Vector2Int(0, -1); yield return new Vector2Int(0, -2); } public List<object> GetDataList() { return new List<object> { leftColumnCount }; } public void SetDataList(List<object> data) { if (data != null && data.Count > 0 && data[0] is int count) { leftColumnCount = Mathf.Clamp(count, 0, 10); } } public void OnSpawn(bool isReadFile = false) { IsPushing = false; m_leftRigidboyd2d.simulated = false; originalPosition = transform.position; GenerateLeftColumns(); } public void OnClick() { } public void OnPlay() { GenerateLeftColumns(); m_leftRigidboyd2d.simulated = true; FRPTRB m_ptRB = m_leftRigidboyd2d.GetComponent<FRPTRB>(); if (!m_ptRB.HasEnterAction()) m_ptRB.SetEnterAction(OnEnter2D); if (!m_ptRB.HasStayAction()) m_ptRB.SetStayAction(OnStay2D); if (!m_ptRB.HasExitAction()) m_ptRB.SetExitAction(OnExit2D); } public void OnStop() { IsPushing = false; backpushing = false; m_leftRigidboyd2d.simulated = false; if (m_leftRigidboyd2d != null) { m_leftRigidboyd2d.velocity = Vector2.zero; m_leftRigidboyd2d.transform.position = originalPosition; } stoppedTime = 0f; //StopCrushDetection(); } #endregion } }帮我看看这段代码有什么问题,我的需求是碰撞发生,然后检测这是个玩家还是物体,假如是玩家则在上中下打三个挤压方向的射线,然后靠射线检测后面是物体还是墙,假如还是物体则递归在物体上也打射线,也检测物体身后直到墙再走后面逻辑。然后假如一开始是物体,则一样的一直递归直到检测到玩家,然后再在玩家身后打三根射线,然后继续递归直到墙。当到了墙,则所有物体都打反方向射线同样递归检测直到是我陷阱本身
最新发布
12-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值