質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.95%

プレイヤーが敵から離れたときや敵が倒れた時に自動でロックオンを非表示にする方法

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 985

score 17

カメラのスクリプトは
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class CameraControllerVer : MonoBehaviour
{
public GameObject player;
public GameObject mainCamera;
public float rotate_speed;
private const int ROTATE_BUTTON = 2;
private const float ANGLE_LIMIT_UP = 60f;
private const float ANGLE_LIMIT_DOWN = -5f;
private LockOnTargetDetector lockOnTargetDetector;
[SerializeField]
public GameObject lockOnTarget;
protected LockonCursor lockonCursor;

void Start()
{
mainCamera = Camera.main.gameObject;
player = GameObject.FindGameObjectWithTag("Player");
lockOnTargetDetector = player.GetComponentInChildren<LockOnTargetDetector>();
lockonCursor = GameObject.FindObjectOfType<LockonCursor>();
}

void LateUpdate()
{
transform.position = player.transform.position;
rotateCmaeraNaturalAngle();
if (Input.GetMouseButton(ROTATE_BUTTON))
{
rotateCmaeraAngle();
}
if (Input.GetButtonDown("Fire2"))
{
if (lockOnTarget == null)
{
// ロックオンターゲット取得
GameObject target = SetTargetClosestScreenCenter();

if (target != null)
{
lockOnTarget = target;
lockonCursor.OnLockonStart(target.transform);                  
}
else
{
// 視点リセット
iTween.RotateTo(gameObject, iTween.Hash(
"rotation", player.transform.eulerAngles,
"time", 0.5f
));
}
}
else
{
// 既にターゲットが設定されていた場合は解除
lockOnTarget = null;
lockonCursor.OnLockonEnd();
}
}

if (lockOnTarget)
{
lockOnTargetObject(lockOnTarget);
}
else
{
rotateCmaeraNaturalAngle();
if (Input.GetMouseButton(ROTATE_BUTTON))
{
rotateCmaeraAngle();
}

}
float angle_x = 180f <= transform.eulerAngles.x ? transform.eulerAngles.x - 360 : transform.eulerAngles.x;
transform.eulerAngles = new Vector3(
Mathf.Clamp(angle_x, ANGLE_LIMIT_DOWN, ANGLE_LIMIT_UP),
transform.eulerAngles.y,
transform.eulerAngles.z
);

}
private void rotateCmaeraNaturalAngle()
{
Vector3 angle = new Vector3(
Input.GetAxis("Angles X") * rotate_speed,
Input.GetAxis("Angles Y") * rotate_speed,
0
);

transform.eulerAngles += new Vector3(angle.y, angle.x);
}
private void rotateCmaeraAngle()
{
Vector3 angle = new Vector3(
Input.GetAxis("Mouse X") * rotate_speed,
Input.GetAxis("Mouse Y") * rotate_speed,
0
) ;

transform.eulerAngles += new Vector3(angle.y, angle.x);
}
private void lockOnTargetObject(GameObject target)
{
transform.LookAt(target.transform, Vector3.up);
}

protected GameObject SetTargetClosestScreenCenter()
{
float search_radius = 15f;

var hits = Physics.SphereCastAll(
player.transform.position,
search_radius,
player.transform.forward,
0.01f,
LayerMask.NameToLayer("LockonTarget")
).Select(h => h.transform.gameObject).ToList();

hits = FilterTargetObject(hits);

if (0 < hits.Count())
{
float min_target_distance = float.MaxValue;
GameObject target = null;

foreach (var hit in hits)
{
Vector3 targetScreenPoint = Camera.main.WorldToViewportPoint(hit.transform.position);
float target_distance = Vector2.Distance(
new Vector2(0.5f, 0.5f),
new Vector2(targetScreenPoint.x, targetScreenPoint.y)
);
Debug.Log(hit.gameObject + ": " + target_distance);

if (target_distance < min_target_distance)
{
min_target_distance = target_distance;
target = hit.transform.gameObject;
}
}

return target;
}
else
{
return null;
}

}

protected List<GameObject> FilterTargetObject(List<GameObject> hits)
{
return hits
.Where(h => {
Vector3 screenPoint = Camera.main.WorldToViewportPoint(h.transform.position);
return screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
})
.Where(h => {
foreach (var component in h.GetComponents<Component>())
{
if (component is Enemy)
{
return true;
}
}
return false;
})
.ToList();
}

}
です。
ちなみに敵の位置を設定し距離でif文をかいたところNUllエラーになります。
どうすれば自動でロックオンを非表示にできるでしょうか?
回答よろしくおねがいします!

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

提示コードが長すぎるので、やり方だけ書いておきます。

LateUpdateメソッド内に

//前略

bool WasLiving=false;

//中略

LateUpdate(){
if(!/*ターゲットが生きているかどうかのフラグ*/&&WasLiving){
//ロックオンを解除する処理
}//前回は生きていたのに、今は生きていない→つまり死んだときの処理

if(lockOnTarget!=null&&(Vector3.Distance(player,lockOnTarget)>/*強制的にロックオンを解除するプレイヤーとターゲットの距離(定数)*/)){
//ロックオンを解除する処理
}//距離が離れ過ぎたときの処理

//中略

WasLiving=/*ターゲットが生きているかどうかのフラグ*/;
}


これで大丈夫だと思いますが、もしダメなら
・ソースコードは「`」×3で囲み、インデントを入れてください。
・メソッドや単位処理にそれぞれ何をしているのかコメントをもっと付けてください。
・ターゲットが倒れるというのは具体的に、”どの変数がどうなることを指すのか”を教えてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/10/16 00:17

    すみません、こちらのミスです。tmp=Vector3.zero;としたら動くと思います。(もし動作したら念のため座標0,0,0に異常がないか確認して下さい)

    キャンセル

  • 2019/10/16 09:42

    すみませんもう一回まとめてもらってもよろしいでしょうか?
    実はロックオンターゲット取得が消えたりして、こんがらがっています。

    キャンセル

  • 2019/10/16 17:24

    新たな回答を追加しました。
    繰り返し言うようですが、インデントは入れて、```で文を囲みましょう

    キャンセル

0

文の最後に
////////←のついている箇所が主な修正部分です

//Edited by kanotoP (2019/10/16-17:09)
using System;////////
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq; 

public class CameraControllerVer : MonoBehaviour{
    public GameObject player;
    public GameObject mainCamera;
    public Single rotate_speed;
    const Int32 ROTATE_BUTTON = 2;
    const Single ANGLE_LIMIT_UP = 60f;
    const Single ANGLE_LIMIT_DOWN = -5f;
    const Single EYESIGHT = 10f;////////離れられる距離の最大
    private LockOnTargetDetector lockOnTargetDetector;
    [SerializeField]public GameObject lockOnTarget;
    protected LockonCursor lockonCursor; 

    void Start(){
        mainCamera = Camera.main.gameObject;
        player = GameObject.FindGameObjectWithTag("Player");
        lockOnTargetDetector = player.GetComponentInChildren<LockOnTargetDetector>();
        lockonCursor = GameObject.FindObjectOfType<LockonCursor>();
    } 

    ///<summary>Updateの後に呼び出されるメソッドです。呼び出し間隔に規定はありません</summary>
    void LateUpdate(){
        transform.position = player.transform.position;
        rotateCmaeraNaturalAngle();
        if (Input.GetMouseButton(ROTATE_BUTTON)){
            rotateCmaeraAngle();
        }

        ////////lockOnTargetの座標を弄りたいならこの場所で
        ////////lockOnTarget.transform.position = ≪新しい座標≫;
        ////////としてください

        if (lockOnTarget == null && Input.GetButtonDown("Fire2")){////////
            // ロックオンターゲット取得
            GameObject target = SetTargetClosestScreenCenter(); 
            if (target != null){
                lockOnTarget = target;
                lockonCursor.OnLockonStart(target.transform);
            }
            else{
                // 視点リセット
                iTween.RotateTo(gameObject, iTween.Hash("rotation", player.transform.eulerAngles, "time", 0.5f));
            }
        }
        if (lockOnTarget != null && (Input.GetButtonDown("Fire2") || Vector3.Distance(lockOnTarget.transform.position, transform.position) > EYESIGHT /*|| "lockOnTargetが死んでいるか"の真偽値*/ )){////////
            // ロックオンターゲット解除
            lockOnTarget = null;
            lockonCursor.OnLockonEnd();
        }
        if (lockOnTarget/*提示ソースには書かれていませんでしたが多分lockOntarget!=nullなのではないですか?*/) lockOnTargetObject(lockOnTarget);////////
        else{
            rotateCmaeraNaturalAngle();
            if (Input.GetMouseButton(ROTATE_BUTTON)) rotateCmaeraAngle();
        }
        Single angle_x = 180f <= transform.eulerAngles.x ? transform.eulerAngles.x - 360 : transform.eulerAngles.x;
        transform.eulerAngles = new Vector3( Mathf.Clamp(angle_x, ANGLE_LIMIT_DOWN, ANGLE_LIMIT_UP), transform.eulerAngles.y, transform.eulerAngles.z); 
    }

    private void rotateCmaeraNaturalAngle(){
        Vector3 angle = new Vector3(Input.GetAxis("Angles X") * rotate_speed, Input.GetAxis("Angles Y") * rotate_speed, 0); 
        transform.eulerAngles += new Vector3(angle.y, angle.x);
    }

    private void rotateCmaeraAngle(){
        Vector3 angle = new Vector3(Input.GetAxis("Mouse X") * rotate_speed, Input.GetAxis("Mouse Y") * rotate_speed, 0) ; 
transform.eulerAngles += new Vector3(angle.y, angle.x);
    }

    private void lockOnTargetObject(GameObject target){
        transform.LookAt(target.transform, Vector3.up);
    } 

    protected GameObject SetTargetClosestScreenCenter(){
        Single search_radius = 15f; 
        var hits = Physics.SphereCastAll(player.transform.position, search_radius, player.transform.forward, 0.01f, LayerMask.NameToLayer("LockonTarget")).Select(h => h.transform.gameObject).ToList(); 
        hits = FilterTargetObject(hits); 
        if (0 < hits.Count()){
            Single min_target_distance = Single.MaxValue;
            GameObject target = null; 
            foreach (var hit in hits){
                Vector3 targetScreenPoint = Camera.main.WorldToViewportPoint(hit.transform.position);
                Single target_distance = Vector2.Distance(new Vector2(0.5f, 0.5f), new Vector2(targetScreenPoint.x, targetScreenPoint.y));
                Debug.Log(hit.gameObject + ": " + target_distance); 
                if (target_distance < min_target_distance){
                    min_target_distance = target_distance;
                    target = hit.transform.gameObject;
                }
            } 
            return target;
        }
        else{
            return null;
        } 
    } 

    protected List<GameObject> FilterTargetObject(List<GameObject> hits){
        return hits.Where(h => {
            Vector3 screenPoint = Camera.main.WorldToViewportPoint(h.transform.position);
            return screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
        }).Where(h => {
            foreach (var component in h.GetComponents<Component>()){
                if (component is Enemy){
                    return true;
                }
            }
            return false;
        }).ToList();
    } 
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • C#に関する質問
  • プレイヤーが敵から離れたときや敵が倒れた時に自動でロックオンを非表示にする方法