わかりを得た

Unityとかゲーム開発について共有できそうなやつ

細長いけど厚みがあるみたいなビルボード

ツイート



こーど

using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;

public class oj_longbullet : MonoBehaviour
{

    public float BaseWidth = 1f;
    public float MaxLength = 5f;
    Camera Cam;
    public Transform Visual;
    private Vector3 velocity;

	void Start()
	{
		velocity = transform.TransformVector(Vector3.forward) * 10f;	//テスト用数値、実際は弾のベロシティを入れる
		Cam = Camera.main;
    }

 void Update()
    {
        if (Visual == null || Cam == null) return;

        Vector3 toCamera = Cam.transform.position - Visual.position;

        Vector3 side = Vector3.Cross(velocity, toCamera);

		const float errordist = 0.001f;
		if (side.sqrMagnitude < errordist) side = Cam.transform.right;

		Vector3 up = Vector3.Cross(side, velocity);
		if (up.sqrMagnitude < errordist) up = Cam.transform.up;

		// カメラから見た方向に常に面を向ける(厚みキープ)
		Visual.rotation = Quaternion.LookRotation(toCamera, up.normalized)*Quaternion.Euler(0,0,90f);

		// 横方向の見え方に応じて長さを調整
		float visualLength = Vector3.Dot(velocity, Visual.right);
		float width = Mathf.Clamp(Mathf.Abs(visualLength), 0f, MaxLength);

		// 横方向に伸ばすスケーリング
		Visual.localScale = new Vector3(BaseWidth + width, BaseWidth, 1f);
    }
}


変なところあったらおしえて

スプライトをランダムに差し替えるツール

とにかくめんどくさい

うちでは背景の賑やかしを作る時に
とりあえずバーッとスプライトを複製して配置してから
絵をいい感じにランダムに差し替えてやることが多いんですが
ランダムの部分を勝手にやってくれる小さなツールを作りました

Sprite Randomizer

ダウンロード

https://deathmofumofu.com/sozai/SpriteRandomizer.cs

  • 例によって適当なところにEditorフォルダを作って入れてください
  • Unityの一番上のメニューのToolsの中に追加されます

使い方

  • まずSprites_Sourceの配列にProject内のSpriteを入れます。複数入ります。
  • その後、Hierarchy内のGameObject(SpriteRendererがくっついていることを忘れずに)を選択状態にします。複数選択できます。
  • 下のボタンを押せば勝手にSprites_Sourceの中のどれかで差し替わります。

それだけ。

他にも

オブジェクトの座標をいじる拙作のツールがあって
それを併用するとシーン内に色々と散らすのが楽になることでしょう。
これです
https://deathmofumofu.com/sozai/#posedit


ほなまた

ベジェ曲線上にオブジェクトを並べる

昔別の場所で書いたコードを再掲します
ベジェ曲線上にパーツを並べるコードです。

こんな感じ

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

[ExecuteInEditMode]
public class eu_bezier : MonoBehaviour {


	public Transform[] controlpoint=new Transform[4];
	public Transform[] g_parts=new Transform[6];

	void Update () 
	{
		
		Vector3[] cp=new Vector3[4];
		for (int k=0;k<4;k++)cp[k]=controlpoint[k].localPosition;


		for (int i=0;i<g_parts.Length;i++)
		{
			float t=i*(1f/(g_parts.Length-1));
			Vector3 pos=Vector3.zero;

			//ベジエ計算
			pos.x=Mathf.Pow(1f-t,3)*cp[0].x+(Mathf.Pow((1f-t),2)*3)*t*cp[1].x+((1f-t)*3)*Mathf.Pow(t,2)*cp[2].x+Mathf.Pow(t,3)*cp[3].x;
			pos.y=Mathf.Pow(1f-t,3)*cp[0].y+(Mathf.Pow((1f-t),2)*3)*t*cp[1].y+((1f-t)*3)*Mathf.Pow(t,2)*cp[2].y+Mathf.Pow(t,3)*cp[3].y;


			//サインカーブでうねらせる場合
			pos.x+=Mathf.Sin((Time.time-(0.1f*i))*5)*0.1f;
			pos.y+=Mathf.Cos((Time.time-(0.1f*i))*8)*0.1f;


			g_parts[i].localPosition=pos;
		}	
	}
}

controlpointにコントロールポイントの空オブジェクトを4つ、
g_partsに並べたいTransformを好きなだけ入れます。
コントロールポイントを動かすと並べられます。あとは流れで

計算式はどっかで読んだのの受け売り……
この書き方だと曲線の真ん中に行くほどオブジェクトの間隔が詰まっていき、端の方は疎になるというデメリットがあります。
曲線上に均等に並べるにはどうしたらいいんだろ……
誰かアドバイス頂ければうれしいです。

過去のテキストコーナーに置きっぱなしのコードがいくつかある(俺も忘れてた)ので
再掲エントリーが続くと思います。
よろしう

ステートマシン

正直この程度の事は誰でも思いついてると思うけど
これについて書いてる記事を見たことがないので一応書いておこ
最初のエントリーだしね

たいへん簡易なタイムライン機能って感じのやつです

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

public class statemachine : MonoBehaviour
{

int state=0;
int count=0;


	void Update()
	{
		if(state==0)
		{
		if(count==50)Debug.Log("state0の50フレーム目です");
		movestate(1,100);	//100f後にstate1へ
		}

		if(state==1)
		{
		if(count==20)Debug.Log("state1の20フレーム目です");
		movestate(0,100);	//100f後にstate0へ
		}

		count++;

	}

	void movestate(int ST,int CT=0)
	{
		if(count>=CT)
		{
		state=ST;
		count=0;		
		}
	}

}


とまあこうすればif(count==***)のフレームでだけ発火するような動作が書けるわけです。
例えばstate1のcount5で弾を撃ち、30f後にstate0に戻るとかね

Update() 内に書くと、144Hzとかのクソ速いディスプレイが繋がってる環境だと爆速で動いてしまうので
FixedUpdate()内に書くとかApplication.targetFrameRate=60;をどっかで入れるとか
そもそもcountをfloatに改造するとか工夫が必要ですが
うちのゲームのキャラクターはだいたいこれをベースにいじったやつで動いてます
変数だけで書けるから好き!

IEnumerator?めんどくさいから使わない


ほなまた