- Home /
Creating a target for bow&arrows game
Hello guys, been trying to create a target (you know, the round one with red and white colors), and the score you get depends on where you hit the target. but ran into an issue
the way I created it, is with cylinders, one behind another, and mesh colliders, the problem is that the arrow pierces through the first cylinder and crosses to another one behind, and therefore gives the wrong score
any idea how to solve this? tryed modifying the arrow's collider but it did'nt work though, still pierces
Answer by Hellium · Oct 25, 2020 at 12:12 AM
I would go with a single cylinder collider and distance calculation from center point.
Following code NOT tested
using UnityEngine;
public class Target : MonoBehaviour
{
[System.Serializable]
public struct Area
{
[Min(0)] public float DistanceFromCenter;
[Min(0)] public int Points;
}
// Create an empty GameObject you place at the center of the target
// The up direction of this empty must be perpendicular to the target surface
[SerializeField] private Transform center;
// Fill inspector
// Order the elements from the smallest to the largest distance
[SerializeField] private Area[] targetAreas;
private void OnCollisionEnter(Collision collision)
{
Plane targetPlane = new Plane(center.up, center.position); // This may be created once in the Start method if the target does not move or rotate
Vector3 contactPoint = targetPlane.ClosestPointOnPlane(collision.contacts[0].point); // Taking the 1st contact point may not be the perfect solution
float distanceFromCenter = Vector3.Distance(contactPoint, center.position);
for (int i = 0 ; i < targetAreas.Length ; i++)
{
if(distanceFromCenter < targetAreas[i].DistanceFromCenter)
{
Debug.Log("The arrow reached the area giving " + targetAreas[i].Points + " points");
break;
}
}
}
// The code below is just to visualise in editor more easily
private void OnDrawGizmosSelected()
{
if (center == null || targetAreas == null)
return;
for (int i = 0 ; i < targetAreas.Length ; i++)
{
DrawWireCircle(center.position, center.up, targetAreas[i].DistanceFromCenter, 8);
}
}
private void DrawWireCircle(Vector3 center, Vector3 normal, float radius, int sides)
{
float deltaAngle = Mathf.PI * 2 / sides;
Vector3 right = Vector3.Dot(normal, Vector3.up) >= 1
? Vector3.Cross(-Vector3.forward, normal).normalized
: Vector3.Cross(normal, Vector3.up).normalized;
Vector3 up = Vector3.Cross(right, normal);
for (int i = 0 ; i < sides ; i++)
{
Vector3 from = right * Mathf.Cos(i * deltaAngle) + up * Mathf.Sin(i * deltaAngle);
Vector3 to = right * Mathf.Cos((i + 1) * deltaAngle) + up * Mathf.Sin((i + 1) * deltaAngle);
Gizmos.DrawLine(from * radius + center, to * radius + center);
}
}
}

Answer by rhapen · Oct 25, 2020 at 12:05 AM
the way i would do it is create empty gameobject in middle of the target and have the target as one colider then calculate distance between stuck arrow and middle of the target gameobject
using https://docs.unity3d.com/ScriptReference/ContactPoint-point.html for getting the coordinates of arrow
Your answer
Follow this Question
Related Questions
Walls Above Player, but both have same Y Axis 2 Answers
CAN I REALISTICALLY MAKE A MMORPG WITH UNITY 3 Answers
An OS design issue: File types associated with their appropriate programs 1 Answer
Script structuring? 2 Answers
UI Design - should you hide it, disable it, or destroy it when it is not in use 2 Answers