基于冲突更改公共变换.基于公共变换更改线渲染器点



我是个新手,似乎无法让它发挥作用。玩家有一根长杆,如果他们戳到某些物体,它会与他们戳到的下一个物体产生类似绳子的连接。这些对象被标记为";PokableObjects";,并且要戳玩家就会点击。我将有数百个不同的可移植对象,我希望柱子上的脚本能适用于所有这些对象。

我想我误解了如何只引用被戳中的物体。我希望Bezier曲线脚本的点,即公共变换,能够适应并成为任何"变换";PokableObject";玩家点击。

这是我的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BCurve : MonoBehaviour
{
//curved line renderer stuff
private LineRenderer lineRenderer;
public Transform p0;
public Transform p1;
public Transform p2;
//Object name detection stuff
bool m_Started;
public LayerMask m_LayerMask;
//Respawn Stuff
private float clickCounter;
public GameObject newPoker;
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
m_Started = true;
clickCounter = 0;
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "PokableObject")
{
Collider[] hitColliders = Physics.OverlapBox(gameObject.transform.position, transform.localScale / 2, Quaternion.identity, m_LayerMask);
if (Input.GetMouseButtonDown(0) && (clickCounter == 0))
{
p0 = Collider.gameObject.position;
clickCounter++;
}


else
{
p2 = Collider.gameObject.position;
//find midpoint between p0 & p2 then lower it's Y coordinate by 1
p1 = ((p0.position.x + p2.position.x) * .05f, ((p0.position.y + p2.position.y) * .05f) - 1), (p0.position.z + p2.position.z) * .05f;
//disable current object and spawn a new one so players can repeat
Instantiate(newPoker, transform.position, Quaternion.Euler(0, 0, 0));
GetComponent<BCurve>().enabled = false;
}
}
}
void Update()
{
DrawQuadraticBezierCurve(p0.position, p1.position, p2.position);
}
void DrawQuadraticBezierCurve(Vector3 p0, Vector3 p1, Vector3 p2)
{
lineRenderer.positionCount = 200;
float t = 0f;
Vector3 B = new Vector3(0, 0, 0);
for (int i = 0; i < lineRenderer.positionCount; i++)
{
B = (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2;
lineRenderer.SetPosition(i, B);
t += (1 / (float)lineRenderer.positionCount);
}
}
}

我们非常感谢所有的帮助。

感谢

  • 首先never使用==比较float值!由于浮点(im(精度的原因,即使在逻辑上你认为它会匹配,这也可能失败。

    例如

    0.2f * 5f / 10f == 1.0f
    

    而不是必然是true,因为它实际上可能是1.00000010.9999999

    这意味着无论如何,使用float作为计数器是没有意义的。你宁愿使用

    int clickCounter;  
    
  • 然后在计算p1时,会有一堆,。看起来这应该被包裹在p1 = new Vector3( .... )

  • 无论如何,您计算的p1不是Transform,而是Vector3位置。你不需要这个场地!稍后只需重新计算DrawQuadraticBezierCurve中的两个Transformp0p2,就可以简单地将其设为

    var p1 = (p0.position + p2.position) * .05f - Vector3.up;
    
  • 不需要LayerMaskOverlapBox,这导致您在任何地方都不使用。你已经有一个标签来检查你的命中

  • Collider.gamObject毫无意义。你想要的是访问与你碰撞的对象的Transform,它就是other.Transform

  • 不需要GetComponent<BCurve>。这个组件已经BCurve,所以可以简单地使用

    enabled = false;
    
  • 但是,一旦获得第二个点,就会禁用该组件,因此Update将不再被调用。

    要么你只想用那一刻的位置画一次线,所以只需立即调用DrawQuadraticBezierCurve并删除整个Update方法。

    或者,如果您的对象可能继续移动,并且您希望继续更新行,则保持Update,但保持启用此组件。

  • 在这两种情况下,只有当您已经拥有两个Transforms时,才应致电DrawQuadraticBezierCurve


所以所有的东西看起来都像这个

public class BCurve : MonoBehaviour
{
//curved line renderer stuff
[SerializeField] private LineRenderer lineRenderer;
public Transform start;
public Transform end;
//Respawn Stuff
public GameObject newPoker;
// I would make this adjustable via the Inspctor
[SerializeField] private int positionCount = 200;
private void Start()
{
if(!lineRenderer) lineRenderer = GetComponent<LineRenderer>();
}
private void OnTriggerStay(Collider other)
{
if(start && end)
{
return;
}
// in general rather use CompareTag instead of ==
// the second silently fails in case of typos and is slightly slower
if (other.CompareTag("PokableObject"))
{
// Then you ALWAYS want to check fr the mouse click, not only 
// if the counter is 0
if(Input.GetMouseButtonDown(0))
{
// you rather want to check here
if (!start)
{
start = other.transform;
}
// I would add a check though to not enable to click on the same object twice
else if (other.transform != start)
{
end = other.transform;
// If you anyway want the line to be drawn only ONCE with the current positions 
// then directly call this here and delete Update completely
//DrawQuadraticBezierCurve(start.position, end.position);
//enabled = false;
// or even
//Destroy(this);
Instantiate(newPoker, transform.position, Quaternion.Euler(0, 0, 0));
}
}
}
}
private void Update()
{
if(start && end)
{
DrawQuadraticBezierCurve(start.position, end.position);
}
}
private void DrawQuadraticBezierCurve(Vector3 p0, Vector3 p2)
{
lineRenderer.positionCount = positionCount;
var inversePositionCount = 1f / positionCount;
var t = 0f;
var p1 = (p0.position + p2.position) * .05f - Vector3.up;
var positions = new Vector3[positionCount];
for (int i = 0; i < lineRenderer.positionCount; i++)
{
var B = (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2;
positions[i] = B;
t += inversePositionCount;
}
// Note: It is WAY cheaper to call this and set all positions at once
lineRenderer.SetPositions(positions);
}
}

derHugo给出了一个惊人的答案,否则是不可能想到的!我添加了一些东西,效果很好。第一件事是确保正在创建一个新的LineRender对象,新的扑克对象将自动引用该对象,并重置起点和终点:

private void Start()
{
if (!lineRenderer) lineRenderer = GetComponent<LineRenderer>();
lineRenderer = Instantiate(lineObject, transform.position, Quaternion.Euler(0, 0, 0)).GetComponent<LineRenderer>();
start = null;
end = null;
destroy = false;
}

第二个是将当前扑克的销毁和新扑克的实例化都移动到LateUpdate,因为这行没有被渲染:

private void LateUpdate()
{
if (destroy == true)
{
Instantiate(newPoker, transform.position, transform.rotation).transform.SetParent(GameObject.Find("MainCamera").transform);
Destroy(this.gameObject);
}
}

再次感谢你对德雨果的帮助!

相关内容

  • 没有找到相关文章

最新更新