Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Carbongrip · Nov 05, 2013 at 01:00 AM · meshweaponhitshield

Detect Shield Mesh Sides Hit

Hey everyone trying to make a 3d mesh shield that can take damage based on side hit. So detect top, bottom, fore, aft, left, right shield hits and those sides take float damage. Right now its working as a single shield and takes damage. Any ideas?

Current weapon script…

 using UnityEngine;
 using System.Collections;
  
 [RequireComponent(typeof(LineRenderer))]
  
 public class BeamArray : MonoBehaviour 
 {
     LineRenderer line;
     public Material lineMaterial;
     bool phaser = false;
     public AudioClip sound;
  
     void Start()
     {
           line = GetComponent<LineRenderer>();
            line.SetVertexCount(2);
            line.renderer.material = lineMaterial;
            line.SetWidth(0.1f, 0.25f);
         line.enabled = false;
     }
     
     void Update()
     {
         var script = GameObject.Find("aaMain Camera").GetComponent<SelectTarget>();
         if(Input.GetKeyDown("space") && phaser == false && script.gui == "yes")
         {
             phaser = true;
             StartCoroutine (pulsetime());
         }
     }
         IEnumerator pulsetime()
         {
             var script = GameObject.Find("aaMain Camera").GetComponent<SelectTarget>();
               line.enabled = true;
             AudioSource.PlayClipAtPoint(sound, Camera.main.transform.position);
               RaycastHit hit;
                if (Physics.Linecast(transform.position, script.selectedTarget.transform.position, out hit))
               {
                  // call ApplyDamage(10) in the hit object:
                    hit.transform.SendMessage("ApplyDamage", 700, SendMessageOptions.DontRequireReceiver);
             }
             //wait the cooldown time in a loop
             float delay = 1.680f;
             while (delay > 0)
             {
                 //update beam endpoints
                 if(script.Shields == false)
                 {
                     line.SetPosition(0, transform.position);
                      line.SetPosition(1, script.selectedTarget.transform.position);
                 }
                 if(script.Shields == true)
                 {
                     line.SetPosition(0, transform.position);
                      line.SetPosition(1, hit.point);
                     script.selectedTarget.GetComponent<MeshRenderer>().enabled = true;
                 }
                 //decrement delay time
                 delay -= Time.deltaTime;
                 //let unity free until next frame
                 yield return null;
             }
                 line.enabled = false;
                 phaser = false;
                 script.selectedTarget.GetComponent<MeshRenderer>().enabled = false;
         }
 }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Huacanacha · Nov 05, 2013 at 11:57 PM 1
Share

How about separate colliders for each section of the shield? You'd have to have a distinct GameObject for each section but they could be children of the Ship or Shield GameObject.

A simpler solution would be to look at the hit position relative to the ships position, and deter$$anonymous$$e left, right, top etc from that. It wouldn't quite have the precision of separate colliders but it's much simpler and might be good enough for your purposes.

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Tomer-Barkan · Nov 05, 2013 at 11:40 PM

No, it's not beyond the capabilities of Unity.

How about you calculate the vector that points from your ship to the target ship, and then using that vector and the enemy ship's "Forward" vector, you can calculate where the ship was hit:

 Vector3 toTarget = script.selectedTarget.transform.position - transform.position;
 Vector3 targetForward = script.selectedTarget.transform.forward; // change to transform.up if it's 2d and the ship faces upwards
 
 float angle = Vector3.Angle(toTarget, targetForward);
     
 if (angle < 45) {
     // less than 45 degrees difference, means we hit him from behind:
     DamageShield("Behind");
 } else if (angle > 135) {
     // more than 135 degrees means the vectors are almost facing each other, so we hit the forward shields:
     DamageShield("Forward");
 } else {
     // degree is between 45 and 135 so we hit from one of the sides. Need to calculate which:
     Vector3 targetRight = script.selectedTarget.transform.right;
     
     // calculate angle between firing vector and target's right vector
     float rightAngle = Vector3.Angle(toTarget, targetRight);
     
     if (rightAngle < 45) {
         // degree less than 45 percent, so we hit behind the right vector, which means we hit the left side of the shields
         DamageShield("Left");
     } else {
         DamageShield("Right");
     }
 }

Of course there are other ways to go about it (several colliders for instance), but this is the simplest way and it should do just fine for most games.

If you want to be even more accurate, instead of using the shooter's position in toTarget, use the position where the weapon hit the shields.


Edit: A solution for working with 6 sides (3d), would be to calculate the angle between the vector pointing from the target center to the hit position, and the 6 directions of the target (forward, back, top, bottom, left, right). The one with the smallest angle is the one that was hit:

 if(script.Shields == true)
 {
    print("shields true and getting side hit");

    // vector from the target center to the hit position
    Vector3 hitDirection = hit.point - script.selectedTarget.transform.position;
    Transform targetTransform = script.selectedTarget.transform;

    float angleForward = Vector3.Angle(hitDirection, targetTransform.forward);
    float angleBack = Vector3.Angle(hitDirection, -(targetTransform.forward));
    float angleRight = Vector3.Angle(hitDirection, targetTransform.right);
    float angleLeft = Vector3.Angle(hitDirection, -(targetTransform.right));
    float angleTop = Vector3.Angle(hitDirection, targetTransform.up);
    float angleBot = Vector3.Angle(hitDirection, -(targetTransform.up));

    string shieldHit = "";
    float minAngle = 180;

    if (angleForward < minAngle) {
      shieldHit = "Forward";
      minAngle = angleForward;
    }

    if (angleBack < minAngle) {
      shieldHit = "Back";
      minAngle = angleBack;
    }

    if (angleRight < minAngle) {
      shieldHit = "Right";
      minAngle = angleRight;
    }

    if (angleLeft < minAngle) {
      shieldHit = "Left";
      minAngle = angleLeft;
    }

    if (angleTop < minAngle) {
      shieldHit = "Top";
      minAngle = angleTop;
    }

    if (angleBot < minAngle) {
      shieldHit = "Bottom";
      minAngle = angleBot;
    }

    print("Shields hit: " + shieldHit);
 }

Note: A cleaner solution would use an array and a for loop, but this is more readable so I use it like this for the sake of the answer.

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Tomer-Barkan · Nov 08, 2013 at 07:20 AM 0
Share

toTarget should be the vector from the hitpoint to the target, not just the hitpoint:

 Vector3 toTarget = script.selectedTarget.transform.position - hit.point

we're trying to calculate which part of the shield was hit (the hit point relative to the target), not the world position of the hit.

avatar image Tomer-Barkan · Nov 08, 2013 at 11:34 PM 0
Share

Then you have to make sure that you enable and disable the shields correctly. The problem might be somewhere in your game logic, because the calculation of where the shields are hit seems to be working correctly.

One thing I noted - you check for script.Shields, but script is the camera game object. Is that really where you store the status of your shields? In the camera?

avatar image Tomer-Barkan · Nov 10, 2013 at 06:46 AM 0
Share

Hmmm.. I'm assu$$anonymous$$g your ship is facing forward. (Z axis).

Try adding:

 toTarget.z = 0;

right after calculating toTarget. This will flatten it for the shield calculations.

avatar image Tomer-Barkan · Nov 10, 2013 at 08:17 AM 0
Share

It's not... I've never seen games with bottom/top shields. Aren't 4 shields enough (so that if it hits the bottom a bit behind, it will be the aft shields, etc)?

The only other trick I can think that will take into account bot/top is to compare the angle of the hit with each of the directions (front/back/left/right/top/bot), and wherever the angle is the smallest, that is the hit:

 // vector from the target center to the hit position
 Vector3 hitDirection = hit.point - script.selectedTarget.transform.position;
 Transform targetTransform = script.selectedTarget.transform;
 
 float angleForward = Vector3.Angle(hitDirection, targetTransform.forward);
 float angleBack = Vector3.Angle(hitDirection, -(targetTransform.forward));
 float angleRight = Vector3.Angle(hitDirection, targetTransform.right);
 float angleLeft = Vector3.Angle(hitDirection, -(targetTransform.right));
 float angleTop = Vector3.Angle(hitDirection, targetTransform.up);
 float angleBot = Vector3.Angle(hitDirection, -(targetTransform.up));

Then compare all the angles, and the one with the smallest angle is the one you want.

Note - please make sure that the transform.position of the target is actually the center of the target, or that will not work.

avatar image Tomer-Barkan · Nov 10, 2013 at 03:11 PM 0
Share

Try my last code section with 6 shield parts, let me know if it works like you expect. If it does, I can change it to 4 sections, if you prefer.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

15 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

I'm trying to add a hitbox to a player. Can I add it to the mesh? 3 Answers

shield if hit get visible? 0 Answers

barycentricCoordinate always return vector(1,0,0) 0 Answers

if shield got hit show 1 Answer

Raycast bug? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges