我制作了一个模型来说明我想要计算的内容。给定两个锚点之间的一条线(向量),我想将一个或多个游戏对象与该矢量的中点成一定距离的切线,并以指定的角度(弧度?)沿着一个垂直于向量的圆。
在这幅图中,一个虚圆位于中点,垂直于锚1和锚2之间的线。我要计算三个点(P1、P2和P3)的P1位置。其目的是将对象放置在每个点上。整个程序集将是一个可以在空间中旋转的游戏对象。(将有一个游戏对象,每个对象都是一个子对象。)

我已经搜索了StackOverflow和团结社区,找不到帮助我完成这三个位置的例子。
有什么想法吗?
发布于 2020-08-07 20:37:24
考虑向量数学和四元数,而不是trig。使用交叉积找到0角偏移量,四元数根据角度旋转它。有关解释,请参见评论。
public void PlaceObjects(Transform anchor1, Transform anchor2, float r,
List<Transform> objs, List<float> angles)
{
// lists must be non-null and same size
Debug.Assert(objs != null);
Debug.Assert(angles != null);
Debug.Assert(objs.Count == angles.Count);
// Find midpoint and axis of rotation
Vector3 midpoint = 0.5f * (anchor1.position + anchor2.position);
Vector3 axis = (anchor2.position - anchor1.position).normalized;
// What direction should the the "zero" offset be based on?
// Base it on the local up of the "assembly parent" this script is attached to?
// or Vector3.up if "0 angle" should approximate world up?
Vector3 upDirection = transform.up;
// Of directions perpendicular to the axis find the closest to upDirection
// See https://stackoverflow.com/a/57698547/1092820 for more information
Vector3 axisRight = Vector3.Cross(upDirection, axis);
if (axisRight == Vector3.zero)
{
// upDirection & axis are colinear, no unique "up-ish" exists.
// Just give up and don't move anything.
return;
}
Vector3 zeroOffsetDir = Vector3.Cross(axis, axisRight);
for (int i = 0 ; i < objs.Count ; i++)
{
Transform obj = objs[i];
float angle = angles[i];
// Find a rotation that describes how to rotate a "0 angle" offset into the one
// the current object needs
Quaternion rot = Quaternion.AngleAxis(angle, axis);
// Find the offset by rotating the "zero" offset, then extending it by the radius
Vector3 offset = r * (rot * zeroOffsetDir);
// Set the object's position based on its offset and the location of the midpoint
obj.position = midpoint + offset;
// Optionally, set the object's rotation based on its current forward and the new up:
// obj.rotation = Quaternion.LookRotation(obj.forward, offset);
}
}发布于 2020-08-08 00:44:30
对于那些感兴趣的人,这是我对@Ruzihm的解决方案的组件改编。PlaceObjectsOnCirclePerpendicularToVectorLine组件放置在一个空的游戏对象上。
using System.Collections.Generic;
using UnityEngine;
public class PlaceObjectsOnCirclePerpendicularToVectorLine : MonoBehaviour
{
// Adapted from https://stackoverflow.com/a/63308834/13052746, by Ruzihm.
public Transform anchor1;
public Transform anchor2;
public float radius;
public List<Transform> objs;
public List<float> angles;
private Vector3 anchor1PriorPosition;
private Vector3 anchor2PriorPosition;
// Start is called before the first frame update
void Start()
{
PlaceObjects(
anchor1,
anchor2,
radius,
objs,
angles);
}
// Update is called once per frame
void Update()
{
PlaceObjects(
anchor1,
anchor2,
radius,
objs,
angles);
}
public void PlaceObjects(
Transform anchor1,
Transform anchor2,
float radius,
List<Transform> objs,
List<float> angles)
{
if (anchor1PriorPosition == anchor1.position &&
anchor2PriorPosition == anchor2.position)
{
// The anchors haven't moved.
return;
} else
{
anchor1PriorPosition = anchor1.position;
anchor2PriorPosition = anchor2.position;
}
// lists must be non-null and same size
Debug.Assert(objs != null);
Debug.Assert(angles != null);
Debug.Assert(objs.Count == angles.Count);
// Find midpoint and axis of rotation
Vector3 midpoint = 0.5f * (anchor1.position + anchor2.position);
Vector3 axis = (anchor2.position - anchor1.position).normalized;
// What direction should the the "zero" offset be based on?
// Base it on the local up of the "assembly parent" this script is attached to?
// or Vector3.up if "0 angle" should approximate world up?
Vector3 upDirection = transform.up;
// Of directions perpendicular to the axis find the closest to upDirection
// See https://stackoverflow.com/a/57698547/1092820 for more information
Vector3 axisRight = Vector3.Cross(upDirection, axis);
//if (axisRight == Vector3.zero)
//{
// // upDirection & axis are colinear, no unique "up-ish" exists.
// // Just give up and don't move anything.
// return;
//}
Vector3 zeroOffsetDir = Vector3.Cross(axis, axisRight);
for (int i = 0; i < objs.Count; i++)
{
Transform obj = objs[i];
float angle = angles[i];
// Find a rotation that describes how to rotate a "0 angle" offset into the one
// the current object needs
Quaternion rot = Quaternion.AngleAxis(angle, axis);
// Find the offset by rotating the "zero" offset, then extending it by the radius
Vector3 offset = radius * (rot * zeroOffsetDir);
// Set the object's position based on its offset and the location of the midpoint
obj.position = midpoint + offset;
}
}
}下面是场景视图中的样子:

下面是这个组件在检查器中的样子:

再来一次,聪明的,鲁兹姆!这正是我想要的!
https://stackoverflow.com/questions/63308574
复制相似问题