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
 

Ben

New member
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. :)

 

sneekyo

Member
Hey Ben,

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

sneekyo

Member
@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
 

Ben

New member
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:

sneekyo

Member
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?
 

DankP3

Active member
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.
 

sneekyo

Member
@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?
 
Top