ダメージ増幅パワーアップの仕掛けを使用します
プレイヤーの攻撃力をダメージ増幅パワーアップから上げたい場合4.0で
制限されていますがVerseからなら上限がありませんでした
ボタンを押した時に攻撃力アップを付与
ダメージ増幅パワーアップは複数用意しなくても数値を変更して使いまわせるので
[player]float 型のMap等で攻撃力を管理できます。
ダメージ増幅パワーアップの仕掛けを使用します
プレイヤーの攻撃力をダメージ増幅パワーアップから上げたい場合4.0で
制限されていますがVerseからなら上限がありませんでした
ボタンを押した時に攻撃力アップを付与
ダメージ増幅パワーアップは複数用意しなくても数値を変更して使いまわせるので
[player]float 型のMap等で攻撃力を管理できます。
ゲームでよくある目に見えないオブジェクトを強調するエフェクト
最初はShaderのパラメータを切り替えて一つのマテリアルで全てやってるのかなとか思ってたんですが
HorizonZeroDawnをやって、エフェクトの下にキャラクターは通常通り描画されていて
「これエフェクト用の別オブジェクトを用意してるだけだ」となり作ってみることにしました。
※追記 ShaderのPassを増やして処理すればできそう。
完成図
まずスキャンする側、今回はShaderGraphを使ってみようと思います
※2021.3.16f1 URPで作成しています
といってもスキャンする側はUnityJapanにあるのでそれを参考にさせて頂きました。
www.youtube.com
Built-inではScriptでDepthTextureを生成するように設定しないといけなかった気がするのでBuilt-inでやろうとしてる人はご注意ください。
次にスキャンされる側を作成します
半透明で描画するだけでいいのですが雰囲気出しのためドット風にします
そしてこのように子オブジェクトにCubeをもう一つ用意して作成したマテリアルに変更します。
しかしこのままでは壁の裏などに隠れているとZTestにより描画されません
そのためZTestを常にパスさせるためにDepthTestをAlwaysに変更します
これでShader部分は完成です。
まずはスキャンされる側のコードです適当ですが
親にこのコンポーネントを付けて
Inspectorで子のハイライト用オブジェクトを指定します
public class HighLightObject : MonoBehaviour { [SerializeField] private GameObject highLightObject; public void StartHilgiht() { StartCoroutine("Count"); } private IEnumerator Count() { highLightObject.gameObject.SetActive(true); yield return new WaitForSeconds(0.7f); highLightObject.gameObject.SetActive(false); } }
次にスキャンする側です
これもスキャンする側にこのコンポーネントとRigidBodyをアタッチします
public class ScanObject : MonoBehaviour { void Update() { transform.localScale += Vector3.one * Time.deltaTime *0.9f; } private void OnTriggerEnter(Collider other) { if (other.transform.TryGetComponent(out HighLightObject obj)) { obj.StartHilgiht(); } } }
今回やること
まずはソースコード
Graphics.Blit関数によりShaderで加工したTextureをコピーするというのを繰り返すことでお絵描きしているように見せてます。
shader側では送られてきたUV座標と現在処理しているUV座標の差がsize以下なら塗りつぶし、それ以外はもとのTextureのまま処理するということをしています。
絵を描くだけではなくVTFを利用したりすることで応用もできます。
参考
nn-hokuson.hatenablog.com
esprog.hatenablog.com
www.youtube.com
RPGを作る課題の時に勝手に作成した副産物を紹介します。
ソースコードかなり汚いから次作る時は直したいところ
難しいことは何もしてないですが応用できそうなので残しておきます。
どちらかと言えばこっからが本題
ScriptableObjectのデータがコンパイル時や再起動時に初期化される現象がおきました
対処としてこちらの記事を参考にしました
tsubakit1.hateblo.jp
私の場合はシリアル化していないのが原因で、EnemyData構造体はシリアライズしてたけどScriptableObjectを継承したEnemyDatasのメンバをprivateで宣言していたためシリアル化されず初期化されてしまいました。
シリアル化についてはこちらを参照しました。
docs.unity3d.com
また、調べている時に別の理由で初期化される場合の記事を見つけたのでリンクしておきます。
kan-kikuchi.hatenablog.com
www.klab.com
Klab株式会社様が運営されているサイトの
www.klab.com
こちらで紹介されている蝶シェーダーを勉強を兼ねて真似してみました。
元の記事では6頂点の板ポリを使用したましたが、今回はテクスチャを貼り付けないので5頂点で行います。
Blender等で出力しても良いのですが、スクリプトで生成することにします。
var mesh = new Mesh(); //meshの頂点 var vertex = new Vector3[]{ new Vector3(-0.1f,0.0f,-0.1f),//左下 new Vector3(0.1f,0.0f,-0.1f),//右下 new Vector3(0.0f,0.0f,0.0f), //中央 new Vector3(-0.1f,0.0f,0.1f),//左上 new Vector3(0.1f,0.0f,0.1f),//右上 }; //meshの三角形を定義 var triangles = new int[]{ 0,3,2, 2,4,1 }; mesh.SetVertices(vertex); mesh.SetTriangles(triangles, 0); //Assetとして出力 AssetDatabase.CreateAsset(mesh, "Assets/ButterflyMesh.asset");
これを適当なスクリプトのStart関数に記載し実行すればAssetにmeshが出力されます。
rotate関数の中身が記載されていなかったのですが、z軸で回転させる回転行列を生成してるだけだと思います。
half2x2 rotate(half theta) { half angleCos = cos(theta); half angleSin = sin(theta); return half2x2(angleCos, -angleSin, angleSin, angleCos); }
ParticleSystemのCustomVertexStreamsを使用して、各パーティクルの中心座標をshaderに送ります。
Custom1.xyはダミーとして入れています。
上の画像のようにCustomVertexSystemはTEXCOORDの使用されていないxyzwから順番に埋めていってしまうので、ダミーを用意し扱い易くしています。
shder側はこのようにして値を受け取ります
struct appdata { float4 vertex : POSITION; float4 uv : TEXCOORD0; //ダミー受け取り用にfloat4を使用 float4 color : COLOR; float4 center:TEXCOORD1; };
元記事にもある通りダイナミックパッチングによるメッシュの結合に対応するために中心座標を受け取って計算しています。
float3 center = v.center; float3 local = v.vertex-center; half flap = _FlapIntensity * sin(_Time.y * _FlapSpeed); local.xy = mul(rotate(flap * sign(local.x)), local.xy); o.vertex = UnityObjectToClipPos(center+local);
これで蝶の仕組みはできたので色々アレンジできそうです。
今回はパーティクルから色を受け取りそれを反映するところで終わりました。