无法从某些起点到某些终点放置射线

huangapple go评论58阅读模式
英文:

Can't place rays from some start to some end

问题

我有一个起点和终点,我需要在从起点到终点的线上放置可调节数量的射线。但我无法弄清楚如何正确放置它们。我几乎完成了,但射线没有放在终点。

绿色 (2, 0, 2) 用于起点,红色 (2, 0, -2) 用于终点,之间的距离为4

这是我的结果,有2条射线,中间的射线应该在终点(红色射线)处,而下一条射线应该在起点和终点射线的中心。

如果我添加第三条射线会发生什么,终点射线的位置没有使用。

以及5条射线。第一条和最后一条射线应该在起点和终点处,其他3条射线应该在它们之间。

这是我的代码:

public class VehicleAroundCast : MonoBehaviour
{
    [SerializeField] private int sideRaysAmount;
    [SerializeField] private Vector3 offset;

    private void Update()
    {
        Vector3 startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
        Vector3 endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;
        float dist = Vector3.Distance(startRayPos, endRayPos);

        Debug.DrawRay(startRayPos, Vector3.down, Color.green);
        Debug.DrawRay(endRayPos, Vector3.down, Color.red);

        for (int i = 0; i < sideRaysAmount; i++)
        {
            float step = dist / sideRaysAmount * i;
            Vector3 position = (transform.position + Vector3.left * offset.x + Vector3.forward * offset.z) + Vector3.back * step;

            Debug.DrawRay(position, Vector3.down);
        }
    }
}
英文:

I have a start and end, i need to place an adjustable amount of rays on the line from start to end. But I can't figure out how to correctle place them. I almost finished, but rays is not placed at the end.

Green (2, 0, 2) for start and Red (2, 0, -2) for end with distance between 4

无法从某些起点到某些终点放置射线

This is my result with 2 rays, the center ray need to be at the end (red ray), and next rays add should be at the center of start and end rays

无法从某些起点到某些终点放置射线

What happens if i adding third ray, the end ray position isn't in use

无法从某些起点到某些终点放置射线

And 5 rays. The first and the last rays need to be at the start and the end. Other 3 rays should to be between

无法从某些起点到某些终点放置射线

This is my code:

public class VehicleAroundCast : MonoBehaviour
{
    [SerializeField] private int sideRaysAmount;
    [SerializeField] private Vector3 offset;

    private void Update()
    {
        Vector3 startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
        Vector3 endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;
        float dist = Vector3.Distance(startRayPos, endRayPos);

        Debug.DrawRay(startRayPos, Vector3.down, Color.green);
        Debug.DrawRay(endRayPos, Vector3.down, Color.red);

        for (int i = 0; i < sideRaysAmount; i++)
        {
            float step = dist / sideRaysAmount * i;
            Vector3 position = (transform.position + Vector3.left * offset.x + Vector3.forward * offset.z) + Vector3.back * step;

            Debug.DrawRay(position, Vector3.down);
        }
    }
}

答案1

得分: 0

以下是代码的翻译部分:

// 通过评论中的澄清,我将做一些不同的事情。我将编辑您的代码,使其按您的需要工作,并在代码注释中进行解释。

public class VehicleAroundCast : MonoBehaviour
{
    [SerializeField] [Min(0)] private int intermediateRayCount;
    // 我将此字段重命名以使名称更具描述性,intermediate 意味着在起始点和结束点之间
    // 为了确保不会分配小于0的数字,我添加了 [Min(0)] 属性,小于0的数字将破坏逻辑并毫无意义

    [SerializeField] private Vector3 offset;

    private void Update ()
    {
        // 我们不希望用大量代码行拥挤 Update() 方法
        // 这样可以更好地维护代码
        CastRays();
    }

    private void CastRays ()
    {
        Vector3 startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
        Vector3 endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;

        // 如果没有中间射线,我们可以节省需要在存在中间射线时的计算
        // 我们只需投射这两条射线,并通过返回结束方法
        if (intermediateRayCount == 0)
        {
            Debug.DrawRay(startRayPos, Vector3.down, Color.green);
            Debug.DrawRay(endRayPos, Vector3.down, Color.red);

            return;
        }

        // 我们将手动计算方向向量,而不是使用 Vector3.Distance()
        // 这样我们不仅可以获得距离(方向向量的大小),还可以获得移动的方向
        Vector3 direction = endRayPos - startRayPos;
        float distance = direction.magnitude;
        direction.Normalize();

        // 我们至少有两条射线(起始和结束),所以总数是在起始和结束之间的射线数加上两条
        int totalRayCount = intermediateRayCount + 2;
        // 个体射线之间的间距,必须从 totalRayCount 中减去一,以便将最后一条射线放在结束位置
        float spacing = distance / (totalRayCount - 1);

        for (int i = 0; i < totalRayCount; i++)
        {
            // 通过将方向乘以间距再乘以当前迭代次数来获取射线位置
            // 由于方向已被归一化,我们可以将其乘以射线之间的距离,从而获得两条射线之间的长度
            // 然后乘以当前射线的编号,即可获得距起始位置的距离和方向
            Vector3 rayPosition = startRayPos + direction * spacing * i;

            // 我添加了一些颜色,以便您可以看到起始和结束
            if (i == 0) 
                Debug.DrawRay(startRayPos, Vector3.down, Color.green);
            else if (i == totalRayCount - 1) 
                Debug.DrawRay(endRayPos, Vector3.down, Color.red);
            else 
                Debug.DrawRay(rayPosition, Vector3.down, Color.white);
        }
    }
}
英文:

Following up from the clarification through the comment I'd do a couple of things a bit different. I'll just edit your code so that it should work as you'd need it to and explain it in code comments.

public class VehicleAroundCast : MonoBehaviour
{
	[SerializeField] [Min(0)] private int intermediateRayCount;
	// I renamed this field so the name is more descriptive, intermediate meaning between start and end
	// to make sure that no number below 0 can be assigned I added the [Min(0)] attribute, a number
	// below 0 would break the logic and wouldn't make sense

	[SerializeField] private Vector3 offset;

	private void Update ()
	{
		// we don't want to clog up our Update() method with tons of lines of code
		// this serves better maintainability as well
		CastRays();
	}

	private void CastRays ()
	{
		Vector3 startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
		Vector3 endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;

		// if we don't have any intermediate rays we can save on the calculation that is necessary when we
		// have intermediates, we just cast the the two rays and end the method by returning
		if (intermediateRayCount == 0)
		{
			Debug.DrawRay(startRayPos, Vector3.down, Color.green);
			Debug.DrawRay(endRayPos, Vector3.down, Color.red);

			return;
		}

		// instead of using Vector3.Distance() we'll calculate the directional vector manually this way
		// we can get not only the distance (directional vectors magnitude) but the direction to move
		// along to space the rays as well

		// subtarting the start position from the end position gives us the directional vector
		Vector3 direction = endRayPos - startRayPos;
		// a directional vectors magnitude gives the distance from start to end
		float distance = direction.magnitude;
		// after the distance has been established we normalize the direction so that it's length is 1
		direction.Normalize();

		// we have at least two rays (start and end) so our total is the rays between start and end plus two
		int totalRayCount = intermediateRayCount + 2;
		// the space between the individual rays, we have to subtract one from the totalRayCount in order to 
		// place the the last ray at the end position (yes this could be optimized but I want to write out 
		// the logic fully so that it's clear what happens)
		float spacing = distance / (totalRayCount - 1);

		for (int i = 0; i < totalRayCount; i++)
		{
			// we can simply get the ray position by adding the direction multiplied by the spacing multiplied
			// by the number of iterations we've gone through to the start position
			// since the direction is normalized we can multiply it by the distance between rays to give it
			// the length between two rays, if we then multiply it by the number of rays the current ray is,
			// we get the distance as well as direction the current ray has to be placed away from the start
			// position
			Vector3 rayPosition = startRayPos + direction * spacing * i;

			// i added some color so you can see start and end
			if (i == 0) 
				Debug.DrawRay(startRayPos, Vector3.down, Color.green);
			else if (i == totalRayCount - 1) 
				Debug.DrawRay(endRayPos, Vector3.down, Color.red);
			else 
				Debug.DrawRay(rayPosition, Vector3.down, Color.white);
		}
	}
}

答案2

得分: 0

是一个简单的逻辑错误。

你希望 sideRaysAmount射线 的数量。但你却将它用作射线之间 步数 的数量。

始终只有比射线少一个步骤。

=> 对于 step 的计算,你只需使用

float step = dist / (sideRaysAmount - 1) * i;

所以例如

var startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
var endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;  

var dist = Vector3.Distance(startRayPos, endRayPos);

var stepSize = sideRaysAmount == 1 ? 0 : dist / (sideRaysAmount - 1f);

Debug.DrawRay(startRayPos, Vector3.down, Color.green);
Debug.DrawRay(endRayPos, Vector3.down, Color.red);

for (var i = 0; i < sideRaysAmount; i++)
{
    var step = i * stepSize;
    var position = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z + Vector3.back * step;

    Debug.DrawRay(position, Vector3.down);
}
英文:

It's a simple logic mistake.

You wanted sideRaysAmount to be the amount of rays. But you are using it as amount of steps in between rays.

There is always exactly one step less than rays.

=> For the calculation of step you simply want to use

float step = dist / (sideRaysAmount - 1) * i;

so e.g.

var startRayPos = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z;
var endRayPos = transform.position + Vector3.left * offset.x + Vector3.back * offset.z;  

var dist = Vector3.Distance(startRayPos, endRayPos);

var stepSize = sideRaysAmount == 1 ? 0 : dist / (sideRaysAmount - 1f);

Debug.DrawRay(startRayPos, Vector3.down, Color.green);
Debug.DrawRay(endRayPos, Vector3.down, Color.red);

for (var i = 0; i < sideRaysAmount; i++)
{
    var step = i * stepSize;
    var position = transform.position + Vector3.left * offset.x + Vector3.forward * offset.z + Vector3.back * step;

    Debug.DrawRay(position, Vector3.down);
}

huangapple
  • 本文由 发表于 2023年2月18日 18:30:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492716.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定