Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
A unity script that can splash a decal prefab (or anything else) in radom direction from a point using raycasting.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Generate paint decals
/// </summary>
public class PainterScript : MonoBehaviour
public static PainterScript Instance;
/// <summary>
/// A single paint decal to instantiate
/// </summary>
public Transform PaintPrefab;
private int MinSplashs = 5;
private int MaxSplashs = 15;
private float SplashRange = 2f;
private float MinScale = 0.25f;
private float MaxScale = 2.5f;
private bool mDrawDebug;
private Vector3 mHitPoint;
private List<Ray> mRaysDebug = new List<Ray>();
void Awake()
if (Instance != null) Debug.LogError("More than one Painter has been instanciated in this scene!");
Instance = this;
if (PaintPrefab == null) Debug.LogError("Missing Paint decal prefab!");
void Update()
// Check for a click
if (Input.GetMouseButtonDown(0))
// Raycast
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
// Paint!
// Step back a little for a better effect (that's what "normal * x" is for)
Paint(hit.point + hit.normal * (SplashRange / 4f));
public void Paint(Vector3 location)
mHitPoint = location;
mDrawDebug = true;
int n = -1;
int drops = Random.Range(MinSplashs, MaxSplashs);
RaycastHit hit;
// Generate multiple decals in once
while (n <= drops)
// Get a random direction (beween -n and n for each vector component)
var fwd = transform.TransformDirection(Random.onUnitSphere * SplashRange);
mRaysDebug.Add(new Ray(location, fwd));
// Raycast around the position to splash everwhere we can
if (Physics.Raycast(location, fwd, out hit, SplashRange))
// Create a splash if we found a surface
var paintSplatter = GameObject.Instantiate(PaintPrefab,
// Rotation from the original sprite to the normal
// Prefab are currently oriented to z+ so we use the opposite
Quaternion.FromToRotation(Vector3.back, hit.normal)
) as Transform;
// Random scale
var scaler = Random.Range(MinScale, MaxScale);
paintSplatter.localScale = new Vector3(
paintSplatter.localScale.x * scaler,
paintSplatter.localScale.y * scaler,
// Random rotation effect
var rater = Random.Range(0, 359);
paintSplatter.transform.RotateAround(hit.point, hit.normal, rater);
// TODO: What do we do here? We kill them after some sec?
Destroy(paintSplatter.gameObject, 25);
void OnDrawGizmos()
if (mDrawDebug)
Gizmos.DrawSphere(mHitPoint, 0.2f);
foreach (var r in mRaysDebug)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment