unity liltoonでタイツを破いたり破かなかったり破いたりしたい
です。なのでやりました。
マテリアルを2つ使って切り替え、が最も簡単だと思いますが、後々数値に変更ができた時にもう一方も変更しにいく、みたいな事はしたくないので、1つのマテリアルでテクスチャだけを切り替えるようにします。同時にアルファマスク用のテクスチャもアタッチして下地が見えるようにします。
また、その下に何かオブジェクトがある場合、その表示、非表示も切り替えるようにします。
なんのために?め、メカバレの時とか・・・かな????
作例のための何かを用意しました。肌色が肌、黒いのがタイツ、青いのが破損時のみ見えて欲しいオブジェクトです。
using UnityEngine;
[ExecuteInEditMode]
public class DamageController : MonoBehaviour
{
public Texture undamagedTexture; // 未破損テクスチャ
public Texture damagedTexture; // 破損テクスチャ
public Texture damagedAlphaMask; // 破損時の透過マスク
public GameObject[] meshesToToggle; // 破損状態で表示・非表示を切り替えるメッシュの配列
private Renderer objectRenderer;
[SerializeField]
private bool isDamaged = false;
void Start()
{
objectRenderer = GetComponent<Renderer>();
if (objectRenderer == null)
{
Debug.LogError("オブジェクトにRendererが見つかりません。");
return;
}
// 初期状態の設定
UpdateDamageState();
}
void OnValidate()
{
// エディタで変数が変更された際に状態を更新
UpdateDamageState();
}
private void UpdateDamageState()
{
if (isDamaged)
{
// 破損テクスチャと透過マスクに切り替え、メッシュを表示
objectRenderer.material.SetTexture("_MainTex", damagedTexture);
objectRenderer.material.SetTexture("_AlphaMask", damagedAlphaMask);
SetMeshesActive(true);
}
else
{
// 未破損テクスチャに切り替え、透過マスクを削除、メッシュを非表示
objectRenderer.material.SetTexture("_MainTex", undamagedTexture);
objectRenderer.material.SetTexture("_AlphaMask", null); // 透過マスクをクリア
SetMeshesActive(false);
}
}
private void SetMeshesActive(bool isActive)
{
foreach (GameObject mesh in meshesToToggle)
{
if (mesh != null)
{
mesh.SetActive(isActive);
}
}
}
}
次にこのスクリプトをテクスチャを切り替えるマテリアルがあるオブジェクトに割り当てます。今回はタイツに割り当てます。
liltoonだとアルファマスク用のテクスチャパラメーターが_AlphaMaskですが、他のシェーダーとかだと_AlphaTexの場合とかがあるようです。
未破損テクスチャ、破損テクスチャ、破損時のアルファマスク、未破損時に隠すオブジェクトを割り当てます。
今回はテストなのでテクスチャはとくに指定してません。
未破損時の状態。隠したいゲームオブジェクトが消えてます。
ダメージ状態の確認。アルファマスクが適応されて透明になり、ゲームオブジェクトが表示されています。
成功です。
やったぜ。
これから毎日タイツを破こうぜ。
あと、私はVRCやってないのでVRCで使えるかはわからないです。
突き抜け防止に複数メッシュのテクスチャを登録できるようにした
実際に利用し始めると、メッシュの動きにより下のメッシュが突き抜けることに気づいた。そこで、複数メッシュを登録してそれぞれ破損未破損テクスチャセットを切り替えられるようにした。
using UnityEngine;
[ExecuteInEditMode]
public class DamageController : MonoBehaviour
{
[System.Serializable]
public class MeshDamageState
{
public GameObject meshObject; // メッシュオブジェクト
public Texture undamagedTexture; // 未破損テクスチャ
public Texture undamagedAlphaMask; // 未破損アルファマスク
public Texture damagedTexture; // 破損テクスチャ
public Texture damagedAlphaMask; // 破損アルファマスク
}
public MeshDamageState[] meshesToToggle; // 破損状態で表示・非表示を切り替えるメッシュの配列
public GameObject[] exposedMeshesOnDamage; // 破損時に露出するメッシュの配列
[SerializeField]
private bool isDamaged = false;
void Start()
{
UpdateDamageState();
}
void OnValidate()
{
// エディタで変数が変更された際に状態を更新
UpdateDamageState();
}
private void UpdateDamageState()
{
foreach (MeshDamageState meshState in meshesToToggle)
{
if (meshState.meshObject != null)
{
Renderer objectRenderer = meshState.meshObject.GetComponent<Renderer>();
if (objectRenderer != null)
{
if (isDamaged)
{
// 破損テクスチャと透過マスクに切り替え
objectRenderer.material.SetTexture("_MainTex", meshState.damagedTexture);
objectRenderer.material.SetTexture("_AlphaMask", meshState.damagedAlphaMask);
}
else
{
// 未破損テクスチャと透過マスクに切り替え
objectRenderer.material.SetTexture("_MainTex", meshState.undamagedTexture);
objectRenderer.material.SetTexture("_AlphaMask", meshState.undamagedAlphaMask);
}
}
else
{
Debug.LogError("オブジェクトにRendererが見つかりません: " + meshState.meshObject.name);
}
}
}
// 破損時に露出するメッシュの表示・非表示を設定
SetExposedMeshesActive(isDamaged);
}
private void SetExposedMeshesActive(bool isActive)
{
foreach (GameObject mesh in exposedMeshesOnDamage)
{
if (mesh != null)
{
mesh.SetActive(isActive);
}
}
}
}