Real Blood

Ben

New member
Hello, just spent some time today getting UCC and Real Blood to work together and I thought I'd share the results. :)

To get the two to work together do the following:

1) Create a C# script named RealBloodShootableObject.cs and paste the following code into it:

C#:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Knife.RealBlood;
using Opsive.Shared.Events;


public class RealBloodShootableObject : MonoBehaviour

{
 public LayerMask ShotMask;

    public void Awake()
    {
        EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
    }

     void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
    {
        //        Debug.Log(name + " impacted by " + attacker + " on collider " + hitCollider + "." + amount);
        var hittable = hitCollider.GetComponent<IHittable>();
        
            Ray r = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
        RaycastHit hitInfo;
            
        if (Physics.Raycast(r, out hitInfo, 1000, ShotMask, QueryTriggerInteraction.Ignore))
        
        if (hittable != null)
        {
            DamageData[] damage = new DamageData[1]
            {
                new DamageData()
                {
                    amount = amount,
                    direction = r.direction,
                    normal = hitInfo.normal,
                    point = hitInfo.point
                  
                    
            }
            };
            
            hittable.TakeDamage(damage);
        }
    

    DebugShot(r, hitInfo);
}

        protected void DebugShot(Ray r, RaycastHit hitInfo)
        {
            if (hitInfo.collider != null)
            {
                Debug.DrawLine(r.origin, hitInfo.point, Color.green, 3f);
            }
            else
            {
                Debug.DrawLine(r.origin, r.GetPoint(1000), Color.red, 3f);
            }
        }

        public Vector3 GetLookDirection()
        {
            return Camera.main.transform.forward;
        }


    public void OnDestroy()
    {
        EventHandler.UnregisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
    }
}

2) Open one of the UCC shooter demo scenes and add DecalsProjector.cs from Real Blood to Nolan.

3) Add one of the prefabs ("doll_for_shooting" for example) from Knife->RealBlood->Prefabs->Demo folder to the demo scene.

4) Copy RealBloodShootableObject.cs onto the prefab children objects that have colliders and set LayerMask to TransparentFX or Everything.

5) Select Nolan's AssaultRifle and make sure that the Impact Layers layer mask includes TransparentFX.

6) Hit play and hopefully it should work and this proved helpful. :)


Real Blood on UAS
 
Just trying out Real Blood on a character model. When adding the material to your own model it's simplest just to copy the material properties from the "doll_for_shooting.prefab" then pasting them into the material on your character. Then just re-add the character's original textures. Also, look closely at the components, layers, and colliders on the "doll_for_shooting.prefab" to set up your character correctly. Remember to add "HitBox.cs" to the objects with the collider.

Something I want to try is to figure out is if there's a way to make the character damage "heal' over time and disappear. Also. if there's a way to randomly apply damage at runtime. That could be useful to make characters automatically look like a zombie or perhaps a dead body just lying around without having to texture paint them.

I think I also should have mentioned that certain features of Real Blood, like the exploding head and the dummy exploding with dynamite, aren't very useful unless you're an animator or have access to one. Also, the documentation is pretty useless and you're better off just examining the demo. But I still think it's worth it for everything else. :)

 
Hey Ben,

Have you experimented with the volumetric blood asset at all? I'm wondering if it's a better choice?
 
@Ben another question, it looks like you figured out how to get explosions and head exploding working, could you explain that a little more?

Thank you so much

-Seth
 
Hey Ben,

Have you experimented with the volumetric blood asset at all? I'm wondering if it's a better choice?


Hey sneekyo, I like them both but personally, I like Real Blood a little bit better. Check my comments in the above video. It also contains the code to get them working together. I still need to experiment more to see what I can and can't do with Volumetric Blood.

I've also been working a little bit with using Paint in 3D as a way to make damage/blood on a character. I think I may be able to get bullet hole decals on a character to "shrink" like they're healing shut.

It's a bit difficult at the moment to formulate an opinion but when I make more progress I'll definitely share the results. :)

Actually, I'll just copy & paste the steps and code for Volumetric Blood since I'm here:

1) Paste the following code into a script. Name the script whatever you want but I named mine VolumeBloodShootableObject.cs.
2) Add the VolumeBloodShootableObject.cs to an object with a collider. Add the Directional Light, AttachedBloodDecal prefab, and Blood prefabs to it. Located in KriptoFX->VolumetricBloodFX->Prefabs.
3) Make sure your Main Camera is set to Deferred and add the BFX_Render Depth component to it.
4) Check the Y position of the ground below the player and add it to the Height setting on the prefabs.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using Opsive.Shared.Events;

public class VolumeBloodShootableObject : MonoBehaviour
{
public LayerMask ShotMask;


//public GameObject Raycaster;
public bool InfiniteDecal;
public Light DirLight;
public bool isVR = true;
public GameObject BloodAttach;
public GameObject[] BloodFX;


Transform GetNearestObject(Transform hit, Vector3 hitPos)
{
var closestPos = 100f;
Transform closestBone = null;
var childs = hit.GetComponentsInChildren<Transform>();

foreach (var child in childs)
{
var dist = Vector3.Distance(child.position, hitPos);
if (dist < closestPos)
{
closestPos = dist;
closestBone = child;
}
}

var distRoot = Vector3.Distance(hit.position, hitPos);
if (distRoot < closestPos)
{
closestPos = distRoot;
closestBone = hit;
}
return closestBone;
}

public Vector3 direction;
int effectIdx;




public void Awake()
{
EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
}

void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
{
// Debug.Log(name + " impacted by " + attacker + " on collider " + hitCollider + "." + amount);
// var hittable = hitCollider.GetComponent<IHittable>();

//Ray r = new Ray(Raycaster.transform.position, Raycaster.transform.forward);
Ray r = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hitInfo;

if (Physics.Raycast(r, out hitInfo, 1000, ShotMask, QueryTriggerInteraction.Ignore))

{
// var randRotation = new Vector3(0, Random.value * 360f, 0);
// var dir = CalculateAngle(Vector3.forward, hit.normal);
float angle = Mathf.Atan2(hitInfo.normal.x, hitInfo.normal.z) * Mathf.Rad2Deg + 180;

//var effectIdx = Random.Range(0, BloodFX.Length);
if (effectIdx == BloodFX.Length) effectIdx = 0;

var instance = Instantiate(BloodFX[effectIdx], hitInfo.point, Quaternion.Euler(0, angle + 90, 0));
effectIdx++;

var settings = instance.GetComponent<BFX_BloodSettings>();
//settings.FreezeDecalDisappearance = InfiniteDecal;
settings.LightIntensityMultiplier = DirLight.intensity;

var nearestBone = GetNearestObject(hitInfo.transform.root, hitInfo.point);
if(nearestBone != null)
{
var attachBloodInstance = Instantiate(BloodAttach);
var bloodT = attachBloodInstance.transform;
bloodT.position = hitInfo.point;
bloodT.localRotation = Quaternion.identity;
bloodT.localScale = Vector3.one * Random.Range(0.75f, 1.2f);
bloodT.LookAt(hitInfo.point + hitInfo.normal, direction);
bloodT.Rotate(90, 0, 0);
bloodT.transform.parent = nearestBone;
//Destroy(attachBloodInstance, 20);
}

// if (!InfiniteDecal) Destroy(instance, 20);

}

}





public float CalculateAngle(Vector3 from, Vector3 to)
{

return Quaternion.FromToRotation(Vector3.up, to - from).eulerAngles.z;

}


public void OnDestroy()
{
EventHandler.UnregisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
}
}
 
Last edited:
That's awesome @Ben I haven't bought either but I'm doing my research and I want to make sure I get the most effective blood. I think based on what you said and what I'm seeing I'd really like to go down the real blood route because of the body part explosion, I really want a lot of gore and gibbing if possible. Also Ben, could you go in to depth a little bit if you don't mind on how to get the explosion/head explosion working correctly?
 
This looks great, thanks. I'm going to wait and see if the real blood dev does SRP support before trying as they don't seem to have good reputation in the reviews and I dont have the time to do myself right now. Really appreciate you sharing your integration though.
 
@Ben I have it all working Ben, with it set up on a rat, everything is working except when I hit it's not taking chunks out of the rat material. It works on the dolls though. Any idea what I'm doing wrong?
 
Hi! This looks great!

I don't have any of the assets, but I'm thinking about buying one. I think that this could be programmed also as a pasive ability for the characters!

Do you mind if I use your base to write a custom ability? (So you wouldn't need to add the script to the character, but just assign the ability!) :)
 
Hello, just spent some time today getting UCC and Real Blood to work together and I thought I'd share the results. :)

To get the two to work together do the following:

1) Create a C# script named RealBloodShootableObject.cs and paste the following code into it:

C#:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Knife.RealBlood;
using Opsive.Shared.Events;


public class RealBloodShootableObject : MonoBehaviour

{
public LayerMask ShotMask;

    public void Awake()
    {
        EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
    }

     void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
    {
        //        Debug.Log(name + " impacted by " + attacker + " on collider " + hitCollider + "." + amount);
        var hittable = hitCollider.GetComponent<IHittable>();
       
            Ray r = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
        RaycastHit hitInfo;
           
        if (Physics.Raycast(r, out hitInfo, 1000, ShotMask, QueryTriggerInteraction.Ignore))
       
        if (hittable != null)
        {
            DamageData[] damage = new DamageData[1]
            {
                new DamageData()
                {
                    amount = amount,
                    direction = r.direction,
                    normal = hitInfo.normal,
                    point = hitInfo.point
                 
                   
            }
            };
           
            hittable.TakeDamage(damage);
        }
   

    DebugShot(r, hitInfo);
}

        protected void DebugShot(Ray r, RaycastHit hitInfo)
        {
            if (hitInfo.collider != null)
            {
                Debug.DrawLine(r.origin, hitInfo.point, Color.green, 3f);
            }
            else
            {
                Debug.DrawLine(r.origin, r.GetPoint(1000), Color.red, 3f);
            }
        }

        public Vector3 GetLookDirection()
        {
            return Camera.main.transform.forward;
        }


    public void OnDestroy()
    {
        EventHandler.UnregisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
    }
}

2) Open one of the UCC shooter demo scenes and add DecalsProjector.cs from Real Blood to Nolan.

3) Add one of the prefabs ("doll_for_shooting" for example) from Knife->RealBlood->Prefabs->Demo folder to the demo scene.

4) Copy RealBloodShootableObject.cs onto the prefab children objects that have colliders and set LayerMask to TransparentFX or Everything.

5) Select Nolan's AssaultRifle and make sure that the Impact Layers layer mask includes TransparentFX.

6) Hit play and hopefully it should work and this proved helpful. :)


Real Blood on UAS
Question: Why not setting it up the same way as the surface effects ? Like BulletOnFlesh and just add the real blood prefab there and the bullethole decal?
 
Hi! This looks great!

I don't have any of the assets, but I'm thinking about buying one. I think that this could be programmed also as a pasive ability for the characters!

Do you mind if I use your base to write a custom ability? (So you wouldn't need to add the script to the character, but just assign the ability!) :)
Did you ever make this as a custom ability?
 
Did you ever make this as a custom ability?
Yes I did it! The core is the same as you presented, but with some differences.

These are:

- You have to override the methods that the ability provides instead of using Unity events (Awake, destroy, etc.)
- Override "IsConcurrent" method and return true.
- Set startup type as Automatic

- And:
public Vector3 GetLookDirection()

You can get this value from one of the overriding methods... I think it's OnAnimatorUpdate (or something like that).

I couldn't test the Ability because I don't have the blood assets, so I just left it waiting :)
 
This works but it doesn't work with using emerald ai.
Sorry for the very late reply. Life has been very complicated. Anyway, it does work but it seems Emerald AI disables colliders on joints at runtime. You can use Emerald AI's Event System to reenable the colliders On Start and disable the colliders On Death if you use ragdoll death. Not sure yet why Emerald AI disables colliders. Guessing it's a physics thing. Still investigating but I hope that info proves useful. :)

 
Emerald AI don't disable Colliders anymore since it using location based damage
Are you sure about that? Because I went through the scripts one by one on the Fallen Guardian prefab to figure out what was disabling the colliders I was adding and it didn't stop until I disabled EmeraldAISystem.cs.

Anyway, you can see that I was able to get EmeraldAI to work with Real Blood and Volumetric Blood in the video.
 
Last edited:
Yeah I'm sure. I just set up a ragdoll , and set up the location based damage script, then added a surface indetifier to the AI and sat up real blood effects in the settings for that surface effect.. worked right away , and I get it pooled..
 
Emerald AI don't disable Colliders anymore since it using location based damage
Okay, I figured what was causing it. It's the scripts EmeraldAIInitializer.cs and EmeraldAIBehaviors.cs that were disabling colliders on joints.

Lines 79 to 117 on EmeraldAIInitializers.cs specifically are disabling box colliders.
 
Top