Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Throwable blade sticking in objects: Looking for the right approach

Discussion in 'Scripting' started by deraggi, Nov 21, 2016.

  1. deraggi

    deraggi

    Joined:
    Apr 29, 2016
    Posts:
    88
    Hi everyone,

    I have a game where the player can throw non-kinematic Rigidbodies around, e.g. blades. To make it more fun, I would like to achieve that a blade sticks in another object, e.g. a wall under realistic circumstances. I could imagine that would be:

    1) Only stick if blade hits the wall with its tip 2) Only stick if blade has a certain velocity normal to the collider mesh of the wall

    For both points I'm not sure what would be the best way to implement them

    Has anyone ever done this? I imagine that it is quite hard to implement this reliably... What would be your approaches for this?

    Thank you so much
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Seemed like a fun little idea, so I took a stab (hehe) at a little prototype: http://imgur.com/3EKqb92

    It's far from perfect but a decent starting point.

    Here's the code for the blade controller:
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class BladeController : MonoBehaviour
    7. {
    8.    public Collider sharpEnd;
    9.  
    10.    private Rigidbody rigidbody;
    11.  
    12.    private void Start()
    13.    {
    14.      rigidbody = GetComponent<Rigidbody>();
    15.    }
    16.  
    17.    private void OnCollisionEnter(Collision collision)
    18.    {
    19.      foreach (ContactPoint contactPoint in collision.contacts)
    20.      {
    21.        // are we hitting with the pointy bit?
    22.        if(contactPoint.thisCollider == sharpEnd)
    23.        {
    24.          // is it going fast enough?
    25.          if (rigidbody.velocity.magnitude >= 20)
    26.          {
    27.            // embed it
    28.            transform.SetParent(contactPoint.otherCollider.transform.root, true);
    29.  
    30.            // destroy this rigidbody so it stops performing physics on the embedded knife
    31.            Destroy(rigidbody);
    32.  
    33.            return;
    34.          }
    35.        }
    36.      }
    37.    }
    38. }
    39.  
    And what the prefab looks like in the hierarchy:


    A couple of tips:
    - If you want just the tip, not the entire blade to stick into something, make sure you set the child collider object to something really small otherwise the whole blade has the potential to stick.
    - You should probably add a check to make sure the blade is facing the right way, assuming only one side is sharp.
    - You'll definitely want to move the blade into the contact point a little bit, before destroying the rigidbody, otherwise you'll see blades kinda floating in mid air since the physics system is pretty good at detecting collisions early so the blade ends up being like... 0.01 units inside, not very convincing visually.
     
  3. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Put a collider on the handle only.

    When the handle collider hits something you work out if it's something it can stick in or bounce out from the OnCollisionEnter() data e.g. normal of surface vs angle of the blade.
     
  4. deraggi

    deraggi

    Joined:
    Apr 29, 2016
    Posts:
    88
    Hehe, awesome guys. Thanks alot. Your Demo rocks :) And is a great test!

    @GroZZleR: I believe one thing is missing - it should not only be decided based on the collider which is hit, but also the impact normal.

    See the following examples, 1 should not stick, 2 does. This is how a blade would stick in reality. The arrow is the blade with its tip, the circle is the object to stick to.

    upload_2016-11-22_12-50-10.png

    Do you have any idea how this can be achieved?

    @Arowx: Wouldn't you miss a lot of cases where a collision occurs? E.g. in example 1) the blade would just fly past thhe object?
     
  5. Mordus

    Mordus

    Joined:
    Jun 18, 2015
    Posts:
    174
    You would have to get the normal of the surface hit and another direction vector pointing down the length of the blade to the point. Then you could work out the difference in angle between the blade and surface and decide whether it sticks or glances off.
     
  6. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    It's just an adaptation of an arrow trick, because the collider is smaller than the object it ends up looking like it is embedded in it when it stops on impact.

    Would your players notice the difference between the two, that depends on the spin speed of the blades and the speed they are thrown?

    Also you could use throwing stars and get around the whole blade handle problem.
     
  7. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Dot-product of 2 direction vectors will tell how much they are aligned to eachother. 2 directions being collision point normal and knifes rotation.forward. Dot-product should always be a number within range 1 to -1 i think, where if it's nearing 0 the angle difference is roughly 90. So i guess you would be asking if it's > 0.7 or something. The smaller value the less demanding it is. Debug.Log the values when collision occurs.
     
    deraggi likes this.
  8. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    If you don't mind me hijacking this thread slightly, I find this quite interesting, how would you do this with particle effects? I've seen demo reels where they have the classic ice spike magic in several bits sticking to the walls the developer has created and then you have slightly more complicated stuff with ice shards falling to the ground and staying there and so on.
     
  9. kru

    kru

    Joined:
    Jan 19, 2013
    Posts:
    452
    Lethn likes this.
  10. deraggi

    deraggi

    Joined:
    Apr 29, 2016
    Posts:
    88
    That's exactly what I needed, thank you so much for this.

    Will try it out!
     
  11. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Added Zaflis' math to the little prototype: http://imgur.com/XbQT6Wz

    Seems to help a lot.

    Code (csharp):
    1.  
    2.   private void OnCollisionEnter(Collision collision)
    3.    {
    4.      foreach (ContactPoint contactPoint in collision.contacts)
    5.      {
    6.        // are we hitting with the pointy bit?
    7.        if(contactPoint.thisCollider == sharpEnd)
    8.        {
    9.          // decent angle?
    10.          if (Vector3.Dot(contactPoint.normal, transform.forward) <= -0.700f)
    11.          {
    12.            // is it going fast enough?
    13.            if (rigidbody.velocity.magnitude >= 5)
    14.            {
    15.              // embed it
    16.              transform.SetParent(contactPoint.otherCollider.transform.root, true);
    17.  
    18.              // destroy this rigidbody so it stops performing physics on the embedded knife
    19.              Destroy(rigidbody);
    20.  
    21.              return;
    22.            }
    23.          }
    24.        }
    25.      }
    26.    }
    27.  
     
    deraggi likes this.
  12. deraggi

    deraggi

    Joined:
    Apr 29, 2016
    Posts:
    88
    Haha, so awesome! Will steal that for my Project ;)

    Thank you so much for this!