Vector3.Dot 判断方位

本文介绍了一种在Unity中判断物体相对位置的方法,利用Vector3的Dot方法来判断物体是否位于另一物体的前、后、左、右。通过具体代码示例展示了如何实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判断方位

假设空间中有这几个坐标,判断一个物体在另一个物体的左边还是右边,前后还是后面

物体空间图

假如以C为中心,判断L是在它的左边还是右边

imageJPATOV8_WLLY$V(4C35`B7X

判断方法

using UnityEngine;
using System.Collections;

public class GetDirection : MonoBehaviour
{
        public Transform cubeF;
        public Transform cubeB;
        public Transform cubeL;
        public Transform cubeR;
        public Transform cubeC;
    
        void Update ()
        {
                Vector3 forward = transform.TransformDirection (Vector3.forward);
                Vector3 toOther = cubeB.position - transform.position;
                if (Vector3.Dot (forward, toOther) < 0) {
                        print ("The other transform is behind me !");
                } else {
                        print ("The other transform is ahead me !");
                }

                Vector3 left = transform.TransformDirection (Vector3.right);
                Vector3 toOtherL = cubeL.position - transform.position;
                if (Vector3.Dot (left, toOtherL) < 0) {
                        print ("The other transform is left me !");
                } else {
                        print ("The other transform is right me !");
                }
        }

}

 

改变位置测试

运行拖动物体在cubeC的不同位置

imageimage

转载于:https://www.cnblogs.com/zhaoqingqing/p/3528417.html

在此基础上需要考虑现实情况,一个建筑的电缆应该都是从一个入口处进入,然后各自走向不同的楼层、房间中去,此时就会出现一开始在同一段管道,后面管道就会分开了,此时如果按照一开始的偏移量来计算,那么就会出现这段管道只用了一部分空间、甚至穿模管道的问题(如果该段管道比初始管道小的话) void LoadMultipleDL(string strData) { if (string.IsNullOrWhiteSpace(strData)) return; List<DLInfo> dLInfoList = JsonMapper.ToObject<List<DLInfo>>(strData); foreach (Transform child in transform.Find("DLList")) { Destroy(child.gameObject); } int cableIndex = 0; // 用于控制偏移和颜色 for (int idx = 0; idx < dLInfoList.Count; idx++) { DLInfo dLInfo = dLInfoList[idx]; string[] deviceNameList = dLInfo.dlPathPoint; List<Vector3> pathPoints = new List<Vector3>(); for (int i = 0; i < deviceNameList.Length; i++) { if (MainBasic.Instance.AllModelChilds.TryGetValue(deviceNameList[i], out Transform obj)) { Vector3 pos = CalculateModelLocalSize(obj.transform); pathPoints.Add(pos); } else { GameObject go = GameObject.Find(deviceNameList[i]); if (go != null) { Vector3 vector3 = CalculateModelLocalSize(go.transform); pathPoints.Add(vector3); } else { print($"无法找到名称为 {deviceNameList[i]} 的游戏对象。"); } } } if (pathPoints.Count < 2) { print($"电缆 {dLInfo.dlName} 至少需要两个点才能生成电缆"); MainBasic.Instance.SendToWebData($"电缆 {dLInfo.dlName} 至少需要两个点才能生成电缆"); continue; } if (!float.TryParse(dLInfo.dlWidth, out float radius)) { print("无效的管道半径:" + dLInfo.dlWidth); MainBasic.Instance.SendToWebData("无效的管道半径:" + dLInfo.dlWidth); continue; } // 偏移距离 float offsetAmount = float.Parse(dLInfo.dlWidth) * 0.025f; // 计算偏移向量 Vector3 pathDirection = (pathPoints[1] - pathPoints[0]).normalized; Vector3 up = Vector3.up; if (Mathf.Abs(Vector3.Dot(pathDirection, Vector3.up)) > 0.99f) up = Vector3.forward; Vector3 totalOffset = ComputeCableOffset(pathDirection, up, cableIndex, offsetAmount, maxLayerNumber); int localIndex = cableIndex % maxLayerNumber; // 动态计算偏移倍数(对称分布) int half = maxLayerNumber / 2; float offsetMultiplier = half - localIndex; float finalOffsetAmount = offsetMultiplier * offsetAmount; // 应用偏移到所有路径点 List<Vector3> offsetPath = new List<Vector3>(); Vector3 previousOffset = Vector3.zero; for (int j = 0; j < pathPoints.Count; j++) { Vector3 offset = Vector3.zero; if (j < pathPoints.Count - 1) { float distanceX = pathPoints[j + 1].x - pathPoints[j].x; float distanceZ = pathPoints[j + 1].z - pathPoints[j].z; if (distanceX > 0) { offset.z += finalOffsetAmount; } else if (distanceX < 0) { offset.z -= finalOffsetAmount; } else { offset.z = totalOffset.z; } if (distanceZ != 0) { offset.x -= finalOffsetAmount; } else { offset.x = totalOffset.x; } offset.y = totalOffset.y + offsetAmount * 0.5f; previousOffset = offset; } else { if (pathPoints.Count == 2) { offset = previousOffset; } else { offset.x = previousOffset.z; offset.z = previousOffset.x; offset.y = previousOffset.y + offsetAmount*0.5f; } } offsetPath.Add(pathPoints[j] + offset); } // 创建电缆物体 GameObject pipeGO = new GameObject(dLInfo.dlName); pipeGO.transform.parent = transform.Find("DLList"); // 设置位置为路径中点 Vector3 dlpos = (offsetPath[0] + offsetPath[offsetPath.Count - 1]) / 2; pipeGO.transform.position = dlpos; // 转换为局部坐标 List<Vector3> localPathPoints = new List<Vector3>(); for (int k = 0; k < offsetPath.Count; k++) { localPathPoints.Add(pipeGO.transform.InverseTransformPoint(offsetPath[k])); } // 添加组件和材质 MeshFilter meshFilter = pipeGO.AddComponent<MeshFilter>(); MeshRenderer meshRenderer = pipeGO.AddComponent<MeshRenderer>(); MeshCollider meshCollider = pipeGO.AddComponent<MeshCollider>(); // 设置材质 meshRenderer.material = new Material(Shader.Find("Clipping/Box/Standard")); Color customColor = new Color32(0xF0, 0x87, 0x0B, 255); meshRenderer.material.color = Color.red; // 根据索引设置颜色 meshRenderer.material.SetFloat("_Metallic", 0.8f); meshRenderer.material.SetFloat("_Glossiness", 0.6f); // 生成管道网格 Mesh pipeMesh = CreateCylinderPipeMesh(localPathPoints, radius * 0.01f); if (pipeMesh.vertexCount > 0) { meshFilter.mesh = pipeMesh; } else { Debug.LogError("生成的管道网格为空!"); Object.DestroyImmediate(pipeGO); } meshCollider.sharedMesh = meshFilter.mesh; cableIndex++; } FocusAutoONDL(strData); } private Vector3 ComputeCableOffset(Vector3 forward, Vector3 up, int cableIndex, float baseOffsetAmount, int maxPerLayer) { // Step 1: 当前层号 和 层内索引 int layer = cableIndex / maxPerLayer; int localIndex = cableIndex % maxPerLayer; // Step 2: Y 轴偏移(每层抬高 baseOffsetAmount) float yOffset = layer * baseOffsetAmount; // Step 3: 主偏移方向(垂直于路径方向Vector3 offsetDir = Vector3.Cross(forward, up).normalized; if (offsetDir == Vector3.zero) offsetDir = Vector3.forward; // 默认方向 // Step 4: 动态计算偏移倍数(对称分布) int half = maxPerLayer / 2; float offsetMultiplier = half - localIndex; // Step 5: 返回最终偏移向量 return offsetDir * offsetMultiplier * baseOffsetAmount + Vector3.up * yOffset; } public class DLInfo { public string dlName; public string dlWidth; public string dlLength; public string dlStart; public string dlEnd; public string[] dlPathPoint; }
06-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值