情報学的バナナの皮

だらだらと自作プログラムについての備忘録

横スク探索ゲームを作りたい!<2>

tkg-lag.hatenablog.com
前回の続きです、二週間程経過しましたがあまり画面的な進展は少ないですけど備忘録なんでね。

今回の成果はこんなもんです。

f:id:tkg_lag:20210503113845p:plain




ー太陽と月の時間システム
朝昼夜を作りたかったのでなんとかしようと考えました。

欲しい機能は太陽or月が見える形で動くこと、画面の色雰囲気が時間帯によって変わること。

sun_moon.transform.rotation =
Quaternion.Euler( (1回当たりの動く角度) * ( (Get_Hour_12() + 6) % 12)+ (1回当たりの動く角度), sun_moon.transform.rotation.y, sun_moon.transform.rotation.z);
とりあえずこんな感じの回転処理で太陽or月を動かします。

時間に合わせて角度を付けてくだけですね。

つぎにこんなクラスを作ります

public class sunlight {
 public Color light_color;//ライトの色
 public float light_power;//ライトの強さ
 public Material light_mat;//SkyBox用のマテリアルを指定
 [Range (0,24)]
 public int time;//何時からこのライトにするか
}

このクラスを朝、昼、夕方、夜用にそれぞれインスタンスを作ってあげてそれを時間帯で使い分けるようにします。

SkyBox用のマテリアルはSkyBox/Proceduralシェーダを使いましょう。ライトの見た目がなんか太陽っぽくなって空気感も出ます。

void sky_mat_change(sunlight change_light) {
 sun_moon_light.color = change_light.light_color;
 sun_moon_light.intensity = change_light.light_power;
 sun_moon_sky.material = change_light.light_mat;
 RenderSettings.skybox = change_light.light_mat;
}

変化させる時間が来たらこのメソッドを走らせます。

sun_moon_lightはDirectional LightオブジェクトについているLightコンポーネント、sun_moon_skyは同じくDirectional LightオブジェクトのSkyBoxコンポーネントです。

RenderSettings.skyboxはウインドウ→レンダリング→ライティング設定から弄れるskyboxの情報です。

ライト自身とライティング設定の両方を切り替えることでそれっぽい空になります。

 

ーアナログ時計を作りたい!

とりあえず試作なので時計盤と針の素材をネット上からもらってきます。

時計盤はここから

時計文字盤(背景白)の無料イラスト素材|イラストイメージ

針はここから

#オリジナル 【フリー素材】時計の文字盤とか針とか。【png透過済】 - とぉるのマンガ - pixiv

それぞれスプライト形式でインポートしてあげます。

針の切り抜き設定はこんな感じ、キモはピポットの位置を針の軸部分に持っていくことです。こうすることでtransform.rotationで回転させたときに簡単に時計っぽい回転になります。

f:id:tkg_lag:20210503111350p:plain

あとは時計盤オブジェクトとその子に時針分針オブジェクトを付けてあげて、

minute_hand.transform.rotation = Quaternion.Euler(0, 0,time_man.Get_Minutes()*(360/60));

こんな感じで時間に同期して回転させてあげればOKです。

カンタンカンタン

ーシーン遷移の時の出現位置を繋げたい

ただシーン遷移しただけだとどう遷移させてもプレイヤーの位置が一定になっちゃいます。

右の扉から出てきた時と左の扉から出てきた時では普通に考えて出現位置が異なりますよね、その処理を書きます。

一番最初に思いつくのは、シーン遷移を担当する扉オブジェクトのインスペクタから遷移後の座標を打ち込んでって方法なんですけど、シーンをまたぐことを考えるとこれは果てしなく面倒くさいですよね…

いちいちシーンを見比べてどこに出すかを決めなきゃいけないしそれを繋がってる扉の両方でしなきゃいけないので手間がかかりすぎます。

考えた結果、現在のシーン内にあるすべての扉の中から遷移前のシーンに繋がっている扉を探査してその扉の前に出現させることにしました。

こうすれば扉オブジェクトを両方のシーンにおいてあげるだけでうまく繋がってくれます。

ついでに扉から出てきた時に左右のどちらを向くかについても処理を加えておきます。

この記事を書いてるときに思いましたが真正面を向いて出てくることもできたほうが便利そうですね。

ということでコードはこんな感じ、ここで使っているObject_Sceneはこのサイトからもらってきたエディタ拡張です。

インスペクタからシーンを設定できるようになるのでとても便利。

baba-s.hatenablog.com

//シーン内のScene_Changerオブジェクトをすべて取得
GameObject objs= GameObject.FindGameObjectsWithTag("Scene_Changer");
//遷移前のシーンとシーン内のScene_Changerが持つシーン情報を比較し、そこからどこにプレイヤーを出現させるかを決定する
for (int i = 0; i < objs.Length; i++) {
 //Object_sceneを取得
 Object_scene scenes = objs[i].GetComponent<Object_scene>();
 //Object_sceneが持つシーン情報が遷移前のものと同じかどうかを比較
 if (scenes.nextscene.m_SceneName == prev_scene) {
  //同じであればプレイヤーの出現位置を決定しbreak
  //向きの左右を決定
  Vector3 tempAngle = Game_Master.Instance.player.transform.eulerAngles;
  tempAngle.y = (scenes.this_dir == Object_scene.dir.Left ? 90f : -90f);
  Game_Master.Instance.player.transform.eulerAngles =tempAngle;
  //Scene_Changerオブジェクトの存在する座標の床の上にキャラを出現させる、もし床に当たらなければそのまま出現
  RaycastHit hit;
  if (Physics.Raycast(objs[i].transform.position, -transform.up, out hit)) {
   Game_Master.Instance.player.transform.position = objs[i].transform.position
   + new Vector3(0, -Mathf.Abs(objs[i].transform.position.y - hit.point.y), 0);
  }
  else {
   Game_Master.Instance.player.transform.position = objs[i].transform.position
   + new Vector3(0, 0, 0);
  }

  break;

 }
}

欠点はすべての扉の中から…ってところのでいでforを回しているので明らかに計算量がかかることですかね。どうしても重かったらコードをなんとか最適化できるよういじります。

 

とりあえずここまでの成果をば

youtu.be

そろそろテキスト処理について考えないとですね…あとはマップ作りか