Home > database >  Way to fix bullet hole z-fighting?
Way to fix bullet hole z-fighting?

Time:12-03

Trying to work myself through basic FPS shooting as practice and I want to have bullet holes where you shoot. However, Texture Z-fighting occurs when I attempt to do so.

The gun works using raycasting like so:

Physics.Raycast(playercam.transform.position, playercam.transform.forward, out hit)

The bullet holes are currently a 2d sprite that I place on the target using this script:

GameObject ceffect = Instantiate(bullethole, hit.point, Quaternion.LookRotation(hit.normal));

theoretically this should work, and it does, however, when it is placed on the world, it Z- fights with the floor texture.

I have tried to render the bullet holes on a different layer, but this simply does not work.

Is there a way to kind of pull the sprite to the top of the object? Am I missing something with the layers? If you need more code, here's my shooting script currently, but look at your own risk.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerShooting : MonoBehaviour
{
    public float fireRate = 2f;
    public float weapon = 1f;
    public float pistoldmg = 5f;
    public Camera playercam;
    public GameObject redblood;
    public GameObject bullethole;
    private float timetofire = 0f;
    void Start()
    {

    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Mouse0) && (Time.time > timetofire))
        {
            timetofire = Time.time   1f / fireRate;
            PistolShoot();
        }
        else if(Input.GetKey(KeyCode.Mouse0))
        {

        }
    }

    void PistolShoot()
    {
        RaycastHit hit;
        if(Physics.Raycast(playercam.transform.position, playercam.transform.forward, out hit))
        {
            Enemy1 enemy = hit.transform.GetComponent<Enemy1>();
            if(enemy != null)
            {
                enemy.Shot(pistoldmg);
                GameObject beffect = Instantiate(redblood, hit.point, Quaternion.LookRotation(hit.normal));
                GameObject ceffect = Instantiate(bullethole, hit.point, Quaternion.LookRotation(hit.normal));
            }
            else 
            {
                GameObject beffect = Instantiate(redblood, hit.point, Quaternion.LookRotation(hit.normal));
                GameObject ceffect = Instantiate(bullethole, hit.point, Quaternion.LookRotation(hit.normal));
            }
        }
    } 
}

`

CodePudding user response:

From the raycast hit information, we get the normal vector, which you're using to rotate the objects. We can use the same normal vector to 'nudge' the objects away from the hit point as well. An example piece of code might look something like this:

void PistolShoot ( )
{
    if ( Physics.Raycast ( playercam.transform.position, playercam.transform.forward, out var hit ) )
    {
        if ( hit.transform.TryGetComponent<Enemy1> ( out var enemy ) )
            enemy.Shot ( pistoldmg );

        var rotation = Quaternion.LookRotation(hit.normal);
        var beffect = Instantiate(redblood, hit.point   hit.normal * 0.01f, rotation );
        var ceffect = Instantiate(bullethole, hit.point   hit.normal * 0.02f, rotation );

        // .. are you using 'beffect' and 'ceffect' after this? There may not be a need to store these.
    }
}

This will nudge the redblood object about "1 cm" away from the hit point, and the bullethole object about "2 cm" away from the hit point. This will likely need to be adjusted to suit your measurements, but if you've followed a one-to-one Unity unit to metre guide, then this will likely do the trick.

Note that some mobile phone use a lower precision when calculating positions, so you might need to increase this value to make it more pronounced.

Here's an example using a slightly exaggerated nudging amount - 0.05 and 0.1 instead of 0.01 and 0.02 - on a 1x1x1 cube. Decal example

  • Related