Ejemplo n.º 1
0
    public override void OnInspectorGUI()
    {
        DecalMaterial decalScript = (DecalMaterial)target;

        serializedObject.Update();

        decalScript.penetrability = EditorGUILayout.Slider("Penetrability", penetrability.floatValue, 0f, 1f);

        if (penetrability.floatValue > 0f)
        {
            decalScript.doesSplatter = EditorGUILayout.Toggle("Does Splatter", doesSplatter.boolValue);
        }

        EditorGUILayout.PropertyField(entryDecals, true);
        EditorGUILayout.PropertyField(entryParticles, true);

        if (penetrability.floatValue > 0f)
        {
            EditorGUILayout.PropertyField(exitDecals, true);
            EditorGUILayout.PropertyField(exitParticles, true);
        }

        if (doesSplatter.boolValue)
        {
            EditorGUILayout.PropertyField(splatterRange);
            EditorGUILayout.PropertyField(splatterDecals, true);
        }

        serializedObject.ApplyModifiedProperties();
    }
    // Will make this Player with <shooterID> shoot over the Network.
    public void Shoot(NetworkInstanceId shooterID)
    {
        Ray ray = new Ray(shootPoint.position, shootPoint.forward);

        // If the muzzle flash is not null then instantiate it at the <shootPoint> position.
        if (muzzleFlash != null)
        {
            GameObject muzzleFlashClone = Instantiate(muzzleFlash, shootPoint.position, shootPoint.rotation) as GameObject;
            Destroy(muzzleFlashClone, 0.05f);
        }

        if (Physics.Raycast(ray, out hit, fireDistance, ~(1 << 8)))
        {
            DecalMaterial decalMaterial = hit.transform.GetComponent <DecalMaterial>();

            if (decalMaterial != null)
            {
                // Calculate the bullets trajectory through DecalMaterial GameObjects.
                decalMaterial.CalculatePenetration(this, shooterID);
            }
        }

        // Play the shot sound if there is one.
        if (shotSound != null)
        {
            AudioSource.PlayClipAtPoint(shotSound, transform.position, 1f);
        }

        if (allowDebugging)
        {
            Debug.DrawRay(shootPoint.position, shootPoint.forward * fireDistance, Color.red);
        }
    }
Ejemplo n.º 3
0
        public static void SaveBakedRederer(string pname, DecalMaterial material, Renderer r)
        {
            var assetDir = AssetDatabase.GetAssetPath(material);

            assetDir = string.IsNullOrEmpty(assetDir) ?
                       "Assets" : Path.GetDirectoryName(assetDir);
            assetDir += "/";
            foreach (var m in r.sharedMaterials)
            {
                if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(m)))
                {
                    AssetDatabase.CreateAsset(m, assetDir + m.name + ".mat");
                }
            }
            // Saving the mesh is not necessary if the decal exists only in the scene, but if
            // moved to a prefab it would otherwise break
            var mesh = (r as SkinnedMeshRenderer)?.sharedMesh ?? r.GetComponent <MeshFilter>().sharedMesh;

            if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mesh)))
            {
                AssetDatabase.CreateAsset(mesh, assetDir +
                                          pname + "_" + r.transform.parent?.name + "_" + material.name + ".asset");
            }
        }
Ejemplo n.º 4
0
    // Will calculate the trajectory of a weapon projectile, affecting the total trajectory distance
    // depending on the penetration value of the hit DecalMaterial's on the trajectory.
    // Will also apply damage to Zombies if they are within the trajectory.
    public void CalculatePenetration(Weapon shotWeapon, NetworkInstanceId shooterID)
    {
        float      shotDistance = shotWeapon.fireDistance;
        Transform  shootPoint   = shotWeapon.shootPoint;
        RaycastHit hit          = shotWeapon.hit;
        Ray        entryRay     = new Ray(shootPoint.position, shootPoint.forward);

        // Calculate the entry raycast and get all the hit information.
        RaycastHit[] entryHits = Physics.RaycastAll(entryRay, shotDistance, ~(1 << 8), QueryTriggerInteraction.Ignore);

        // Sort the entry hits from smallest to biggest distance.
        Array.Sort(entryHits, delegate(RaycastHit hitA, RaycastHit hitB)
        {
            return(hitA.distance.CompareTo(hitB.distance));
        });

        // Get the end point of the total trajectory, so we can raycast back to the origin.
        Vector3 rayEndPoint    = shootPoint.position + (shootPoint.forward * shotDistance);
        float   offsetDistance = Vector3.Distance(rayEndPoint, hit.point);
        Ray     exitRay        = new Ray(rayEndPoint, hit.point - rayEndPoint);

        // Calculate the exit raycast and get all the hit information.
        RaycastHit[] exitHits = Physics.RaycastAll(exitRay, offsetDistance, ~(1 << 8), QueryTriggerInteraction.Ignore);

        // Sort the exit hits from smallest to biggest distance.
        Array.Sort(exitHits, delegate(RaycastHit hitA, RaycastHit hitB)
        {
            return(hitA.distance.CompareTo(hitB.distance));
        });

        float finalTravelDistance = shotDistance;

        for (int i = 0; i < entryHits.Length; i++)
        {
            // Calculate the entry hits and decals.

            // If the root object of the collider we hit in the trajectory is a zombie, then apply damage to him.
            if (entryHits[i].transform.root.tag == "Zombie")
            {
                ZombieAI hitZombie = entryHits[i].transform.root.GetComponent <ZombieAI>();

                // If we hit the Zombie's head, subtract all he has left for health from his remainder health.
                float totalDamage = (entryHits[i].collider.name == "Head") ? hitZombie.currentHealth : shotWeapon.shotDamage;

                // Apply the damage to the zombie.
                hitZombie.TakeDamage(totalDamage, shooterID);
            }

            // Get the DecalMaterial from this entry hit object.
            DecalMaterial hitMaterial = entryHits[i].collider.GetComponent <DecalMaterial>();

            // If this entry hit object does not have a DecalMaterial, then return and ignore further calculations for this entry hit.
            if (hitMaterial == null)
            {
                continue;
            }

            // Check if the entry point of the projectile was still inside the current final travel distance
            // after penetration discounts have been made.
            if (entryHits[i].distance <= finalTravelDistance)
            {
                CreateDecal(entryHits[i], hitMaterial, DecalType.Entry);

                // Check if there is a object hit after this entry hit (for splatter calculations).
                if (entryHits.Length - 1 >= i + 1)
                {
                    // Get the entry hit after this one.
                    RaycastHit splatterHit = entryHits[i + 1];

                    // Check if the current hit material splatters and that the next hit object is within splatter range.
                    if (hitMaterial.doesSplatter && (splatterHit.distance <= splatterRange))
                    {
                        CreateDecal(splatterHit, hitMaterial, DecalType.Splatter);
                    }
                }
            }
            else
            {
                break;
            }

            // Affect the final travel distance depending on the hit objects material penetrability.
            finalTravelDistance *= hitMaterial.penetrability;

            // Check if there is a exit hit for the current entry hit.
            if (exitHits.Length - 1 >= i)
            {
                RaycastHit currentExitHit = exitHits[exitHits.Length - 1 - i];

                // Check if the exit decal is within the projectile travel distance.
                if (Vector3.Distance(currentExitHit.point, shootPoint.position) <= finalTravelDistance)
                {
                    CreateDecal(currentExitHit, hitMaterial, DecalType.Exit);
                }
            }
        }

        Debug.DrawRay(shootPoint.position, shootPoint.forward * finalTravelDistance, Color.blue, 2000f);
    }
Ejemplo n.º 5
0
    // Will create and configure a decal and particle based on given RaycastHit and DecalMaterial information from the hit object.
    private void CreateDecal(RaycastHit raycastHit, DecalMaterial hitMaterial, DecalType decalType)
    {
        // Calculate the position and rotation for this decal based on the RaycastHit.
        Vector3    decalOffset   = raycastHit.point + (raycastHit.normal * 0.002f);
        Quaternion decalRotation = Quaternion.FromToRotation(Vector3.up, raycastHit.normal);

        Decal targetDecal    = new Decal();
        Decal targetParticle = new Decal();

        int randomIndex = 0;

        switch (decalType)
        {
        case DecalType.Entry:
            if (hitMaterial.entryDecals.Count > 0)
            {
                randomIndex = UnityEngine.Random.Range(0, hitMaterial.entryDecals.Count);
                targetDecal = hitMaterial.entryDecals[randomIndex];
            }

            if (hitMaterial.entryParticles.Count > 0)
            {
                randomIndex    = UnityEngine.Random.Range(0, hitMaterial.entryParticles.Count);
                targetParticle = hitMaterial.entryParticles[randomIndex];
            }
            break;

        case DecalType.Exit:
            if (hitMaterial.exitDecals.Count > 0)
            {
                randomIndex = UnityEngine.Random.Range(0, hitMaterial.exitDecals.Count);
                targetDecal = hitMaterial.exitDecals[randomIndex];
            }

            if (hitMaterial.exitParticles.Count > 0)
            {
                randomIndex    = UnityEngine.Random.Range(0, hitMaterial.exitParticles.Count);
                targetParticle = hitMaterial.exitParticles[randomIndex];
            }
            break;

        case DecalType.Splatter:
            if (hitMaterial.splatterDecals.Count > 0)
            {
                randomIndex = UnityEngine.Random.Range(0, hitMaterial.splatterDecals.Count);
                targetDecal = hitMaterial.splatterDecals[randomIndex];
            }
            break;
        }

        // Create the decal.
        if (targetDecal.decalObject != null)
        {
            GameObject decal = Instantiate(targetDecal.decalObject, decalOffset, decalRotation) as GameObject;

            decal.transform.parent = raycastHit.transform;
            decal.name             = decalType + " Decal";

            Destroy(decal, targetDecal.duration);
        }

        if (targetParticle.decalObject != null)
        {
            // If there is a particle, then create it and destroy it in a second.
            Destroy(Instantiate(targetParticle.decalObject, decalOffset, decalRotation), targetParticle.duration);
        }
    }