Unity C# ランゲーム:敵の攻撃の狙いをランダムにする方法について!!
こんにちは、連日 Qiitaで質問させて頂いてます。はせがわです。
また、皆さんのお力をお借りしたく質問させて頂きます。
今作っている物
Unityで
「盾一枚で依頼人を敵の攻撃から守りながらゴールまで送り届けるランゲーム」
を作っています。
プレイヤーは、自動前進で敵がPlayerまたは依頼人を狙って放物線上に飛んできます。
※現状は、playerのみをターゲットにしています。
実現したい事
敵の攻撃は、3パターン作り、そのパターンをランダムで実行したいと思っています
パターン1は、プレイヤーをそのまま狙ってくるパターン
パターン2は、依頼人を狙ってくるパターン
パターン3は、下記のペライチのような、ランダム範囲で攻撃してくる
しかし、現状 Z軸が動いてしまい、盾の後ろの方にターゲットが移動してしまいます。
※現在、ターゲットは、プレイヤーの前身移動速度を考慮して、盾の少し前に設定しています。
Z位置は、そこで固定して YとX軸だけでターゲットがばらついてほしいと思っています。
【参考動画】
https://youtu.be/-LhvG5ULkfk
クリアしたい課題
・3つ目の ランダム攻撃が実装できません。
どうか、お力を貸してください。。。
[Github]
https://github.com/hasegawadesu/ShieldRunner-VR-.git
[射出Code]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class throwingscript : MonoBehaviour
{
//☆
private float InstantiationTimer = 0f;
// ターゲットオブジェクトの Transformコンポーネントを格納する変数
public Transform target;//☆
// オブジェクトの移動速度を格納する変数
public float moveSpeed;//☆
// オブジェクトが停止するターゲットオブジェクトとの距離を格納する変数
public float stopDistance;//☆
// オブジェクトがターゲットに向かって移動を開始する距離を格納する変数
public float moveDistance;//☆
//<summary>
//testtest
//射出するオブジェクト
//</summary>
[SerializeField, Tooltip("ThrowingObject")]
private GameObject ThrowingObject=null;
//<summary>
//標的のオブジェクト
//</summary>
[SerializeField, Tooltip("TargetObject")]
private GameObject TargetObject=null;
//<summary>
//射出角度
//</summary>
[SerializeField, Range(0F,90F), Tooltip("ThrowingAngle")]
private float ThrowingAngle=0;
// Start is called before the first frame update
private void Start()
{
Collider collider = GetComponent<Collider>();
if(collider != null)
{
//干渉しないようにisTriggerをつける
collider.isTrigger = true;
}
}
// Update is called once per frame
void Update()
{
// ゲーム実行中に毎フレーム実行する処理
//☆ 変数 targetPos を作成してターゲットオブジェクトの座標を格納
Vector3 targetPos = target.position;//☆
// 自分自身のY座標を変数 target のY座標に格納
//(ターゲットオブジェクトのX、Z座標のみ参照)
targetPos.y = transform.position.y;//☆
// オブジェクトを変数 targetPos の座標方向に向かせる
transform.LookAt(targetPos);//☆
// 変数 distance を作成してオブジェクトの位置とターゲットオブジェクトの距離を格納
float distance = Vector3.Distance(transform.position, target.position);//☆
// オブジェクトとターゲットオブジェクトの距離判定
// 変数 distance(ターゲットオブジェクトとオブジェクトの距離)が変数 moveDistance の値より小さければ
// さらに変数 distance が変数 stopDistance の値よりも大きい場合
if (this.transform.position.z-15 < target.transform.position.z)
{
Destroy(gameObject);
}
else if (distance < moveDistance && distance > stopDistance)//☆
{
ThrowingBall();
}
}
//<summary>
//ボールを射出する
//</summary>
private void ThrowingBall()
{
InstantiationTimer -= Time.deltaTime;
if (ThrowingObject !=null && TargetObject !=null && InstantiationTimer <0)
{
//Ballオブジェクトの生成
GameObject ball = Instantiate(ThrowingObject, this.transform.position, Quaternion.identity);
InstantiationTimer =2f;
//標的の座標
float x = Random.Range(0.0f, 2.0f);
float y = Random.Range(0.0f, 2.0f);
float z = Random.Range(0.0f, 2.0f);
Vector3 targetPosition = TargetObject.transform.position;
TargetObject.transform.position = new Vector3(x, y, z);
//射出角度
float angle = ThrowingAngle;
//射出速度を算出
Vector3 velocity = CalculateVelocity(this.transform.position, targetPosition, angle);
//射出
Rigidbody rid = ball.GetComponent<Rigidbody>();
rid.AddForce(velocity * rid.mass, ForceMode.Impulse);
}
}
//<summary>
//標的に命中する射出速度の清算
//</summary>
//<param name="pointA">射出開始座標</param>
//<param name="pointB">標的の座標</param>
//<returns>射出速度</returns>
private Vector3 CalculateVelocity(Vector3 pointA, Vector3 pointB, float angle)
{
//射出角をラジアンに変換
float rad = angle * Mathf.PI / 180;
//水平方向の距離x
float x = Vector2.Distance(new Vector2(pointA.x,pointA.z),new Vector2(pointB.x, pointB.z));
//垂直方向の距離y
float y = pointA.y - pointB.y;
//斜方投射のこうしきを初速度について解く
float speed = Mathf.Sqrt(-Physics.gravity.y * Mathf.Pow(x,2)/(2*Mathf.Pow(Mathf.Cos(rad),2)*(x * Mathf.Tan(rad)+y)));
if(float.IsNaN(speed))
{
//条件を満たす初速を算出できなければVector3.zeroを返す
return Vector3.zero;
}
else
{
return (new Vector3(pointB.x - pointA.x, x * Mathf.Tan(rad), pointB.z-pointA.z).normalized*speed);
}
}
}
なにとぞ、よろしくお願いします。