我们有一种方法可以检测炮弹是否与直线渲染的土耳其物体碰撞。基本上,我们有方法在绘制的线条中获取火鸡的所有线条。然后我们检查炮弹中心到直线的距离是否小于炮弹半径。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class canonTrajectory : MonoBehaviour
{
GameObject[] turkeyList = new GameObject[5];
GameObject turkeys;
public static float rotationAngle;
float createdTime;
float speed = 150f;
float gravity = -200.0f;
public GameObject turkey;
static int NUM_PARTICLES = 26;
Vector3[] m_position = new Vector3[NUM_PARTICLES];
LineRenderer lineRenderer;
void Start()
{
turkeys = GameObject.Find("Turkeys");
for (int i = 0; i<5; i++)
{
turkeyList[i] = turkeys.transform.GetChild(i).gameObject;
}
}
// Update is called once per frame
void FixedUpdate()
{
float directionx = Mathf.Cos(-rotationAngle*2.0f*Mathf.PI/360.0f);
float directiony = Mathf.Sin(-rotationAngle * 2.0f * Mathf.PI / 360.0f);
Debug.Log(-rotationAngle * 2.0f * Mathf.PI / 360.0f);
float directionVectorLength = Mathf.Pow(Mathf.Pow(directionx, 2) + Mathf.Pow(directiony, 2), (0.5f));
transform.Translate(-5 * directionx, 5 * directiony , 0.0f);
if (transform.position.x < -300)
Destroy(gameObject);
if (transform.position.y < -77)
Destroy(gameObject);
CheckForTouchingTurkey();
}
public bool CheckForTouchingTurkey()
{
for (int i = 0; i < turkeyList.Length; i++)
{
Vector2 [] temporaryTurkeyLines = turkeyList[i].gameObject.GetComponent<MoveTurkey>().GetSlopeAndIntercept();
for (int j = 0; j < temporaryTurkeyLines.Length;j++)
{
float distance = Mathf.Abs(transform.position.x * temporaryTurkeyLines[i].x -transform.position.y + temporaryTurkeyLines[i].y) / Mathf.Sqrt(1 + Mathf.Pow(temporaryTurkeyLines[i].x, 2.0f));
Debug.Log("distance between ball and turkey is:" + distance);
if (distance < 2.5f)
{
turkeyList[i].gameObject.GetComponent<MoveTurkey>().UpdateMPosition(-20f);
Destroy(gameObject);
}
}
}
return false;
}
}
土耳其运动脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveTurkey : MonoBehaviour
{
LineRenderer lineRenderer;
static int NUM_PARTICLES = 26;
float fTimeStep;
Vector3[] m_position = new Vector3[NUM_PARTICLES];
Vector3[] m_acceleration = new Vector3[NUM_PARTICLES];
Vector3[] m_oldPosition = new Vector3[NUM_PARTICLES];
Vector2[] slopeAndIntercept = new Vector2[NUM_PARTICLES - 1];
public Transform fireball;
float gravity = -9.8f;
// Start is called before the first frame update
public void UpdateMPosition(float x)
{
for (int i = 0; i < m_position.Length; i++)
m_position[i].x +=x;
}
public Vector2[] GetSlopeAndIntercept()
{
return slopeAndIntercept;
}
void Start()
{
fTimeStep = 0.5f;
lineRenderer = gameObject.GetComponent<LineRenderer>();
lineRenderer.GetPositions(m_position);
for (int i = 0; i < m_acceleration.Length; i++)
{
m_acceleration[i] = new Vector3(0.0f, gravity, 0.0f);
}
}
// Verlet integration step void ParticleSystem::
void Verlet()
{
for (int i = 0; i < NUM_PARTICLES; i++)
{
m_position[i] = 2 * m_position[i] - m_oldPosition[i] + m_acceleration[i] * fTimeStep * fTimeStep;
m_oldPosition[i] = m_position[i];
}
}
public void FindLinesOfTurkey()
{
for (int i = 0; i < slopeAndIntercept.Length; i++)
{
float slope = (m_position[i + 1].y - m_position[i].y) / (m_position[i + 1].x - m_position[i].x);
float intercept = m_position[i].y - slope * m_position[i].x;
slopeAndIntercept[i].x = slope;
slopeAndIntercept[i].y = intercept;
}
}
// Update is called once per frame
void Update()
{
//Codes for when the Turkey do the random jump
int rn_generator = Random.Range(0, 2000);
if (rn_generator < 5 && m_position[17].y<=-255f)
{
for (int i = 0; i < m_acceleration.Length; i++)
m_acceleration[i].y = 6.0f; //m_acceleration[i].y;
}
if(m_position[13].y> 90.0f && m_acceleration[13].y>0.0f)
for (int i = 0; i < m_acceleration.Length; i++)
m_acceleration[i].y = -9.8f; //m_acceleration[i].y;
//call verlet
Verlet();
FindLinesOfTurkey();
//check proper orientation of the Turkey( turned left or right)
if (m_position[4].x < m_position[13].x && m_acceleration[25].x >= 0)
{
Vector3 sumOfPoints = new Vector3();
Vector3 sumOfPointsOld = new Vector3();
int numberOfPointsAdded = 0;
Vector3 centerOfTurkey = new Vector3();
Vector3 centerOfTurkeyOld = new Vector3();
for (int i = 8; i < m_position.Length; i++)
{
sumOfPoints.x += m_position[i].x;
sumOfPointsOld.x += m_oldPosition[i].x;
numberOfPointsAdded++;
}
centerOfTurkey.x = sumOfPoints.x / numberOfPointsAdded;
centerOfTurkeyOld.x = sumOfPointsOld.x / numberOfPointsAdded;
for (int i = 0; i < m_position.Length; i++)
{
m_position[i].x = (centerOfTurkey.x + centerOfTurkey.x - m_position[i].x);
m_oldPosition[i].x = (centerOfTurkeyOld.x + centerOfTurkeyOld.x - m_oldPosition[i].x);
}
}
else if (m_position[4].x > m_position[13].x && m_acceleration[25].x < 0)
{
Vector3 sumOfPoints = new Vector3();
Vector3 sumOfPointsOld = new Vector3();
int numberOfPointsAdded = 0;
Vector3 centerOfTurkey = new Vector3();
Vector3 centerOfTurkeyOld = new Vector3();
for (int i = 8; i < m_position.Length; i++)
{
sumOfPoints.x += m_position[i].x;
sumOfPointsOld.x += m_oldPosition[i].x;
numberOfPointsAdded++;
}
centerOfTurkey.x = sumOfPoints.x / numberOfPointsAdded;
centerOfTurkeyOld.x = sumOfPointsOld.x / numberOfPointsAdded;
for (int i = 0; i < m_position.Length; i++)
{
m_position[i].x = (centerOfTurkey.x + centerOfTurkey.x - m_position[i].x);
m_oldPosition[i].x = (centerOfTurkeyOld.x + centerOfTurkeyOld.x - m_oldPosition[i].x);
}
}
else
Debug.Log("Nothing");
//if the turkey is on the ground , remove gravity
if (m_position[17].y <= -255 && m_position[22].y <= -255)
{
float rdGenerator = Random.Range(0.0f, 1.0f);
if (rdGenerator > 0.5f)
{
for (int i = 0; i < m_acceleration.Length; i++)
{
if (m_acceleration[25].x == 0)
m_acceleration[i].x = 3.0f;
m_acceleration[i].y = 0.0f;
}
}
else
{
for (int i = 0; i < m_acceleration.Length; i++)
{
if (m_acceleration[25].x == 0)
m_acceleration[i].x = -3.0f;
m_acceleration[i].y = 0.0f;
}
}
}
// change direction of turkey when they hit the wall or the mountain
if (m_position[13].x >= 280)
{
for (int i = 0; i < m_acceleration.Length; i++)
m_acceleration[i].x = -2.0f;
}
if (m_position[4].x <= -90)
{
for (int i = 0; i < m_acceleration.Length; i++)
m_acceleration[i].x = 2.0f;
}
//draw the turkey
lineRenderer.SetPositions(m_position);
}
}
但是代码不起作用。炮弹穿过火鸡,就好像它们不在那儿一样。
答案 0 :(得分:1)
您只需检查火鸡+炮弹的半径,即可检查距每个火鸡中心的距离。
Vector2 ballPos = cannonball.transform.position;
float turkeyRadius = 0.5f; // we'll assume it has a circle as a hitbox/collider
float cannonBallRadius = 0.1f; // same for the cannonball
// We want the radiuses squared, because we wanna compare with sqrMagnitude later.
float minDifToCollide = cannonBallRadius * cannonBallRadius + turkeyRadius * turkeyRadius;
foreach (var turkey in allTurkeys) {
Vector2 turkeyPos = turkey.GetCenter();
// .sqrMagnitude is more performant than .magnitude, so we use that.
float dif = (turkeyPos - ballPos).sqrMagnitude;
// Check for collision.
if (dif <= minDifToCollide) { CollideWith(turkey); }
}
您可以将这段代码添加到火鸡中,以便可视化它们的半径:
public float Radius;
void OnDrawGizmos() {
Gizmos.color = Color.teal;
Gizmos.DrawWireSphere(transform.position, Radius);
}