Unityでワイヤーアクションを作りたいメモ

おかしなところなどあればTwitterで教えて欲しいです。(ブログにコメントを書いてもらえると嬉しいですがハードルが高いのといつでも反応できるわけではないので)
Teitter:@ritz_prgrm
Raycastを使ったもので作った。
Raycastを使わなくてもいいとは思う。
使ったのはPlayer(Cube),PlayerCamera(camera),Anker,AnkerLine
コードが必要なのはPlayerとPlayerCameraのみ。AnkerとAnkerLineはPrefabでなんでもいいが今回はCubeを使った。AnkerLineにいろをつけたかったらMaterialつける。インデントがゴミ。

PlayerCameraはPlayerの子オブジェクト
Cubeでしかまだ使っていないので注意。
アタッチしてAnkerPrefab,AnkerLinePrefabにはオブジェクトをいれる。
Player(RigidBody付でAngular drag,Dragは0。ConstraintsでFreezeRotation yにチェック)

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

public class Player : MonoBehaviour
{
    public float inputHorizontal;
    public float inputVertical;
    public Rigidbody rigidBody;
    //インスペクタでAnkerPrefabとAnkerLinePrefabになにかオブジェクトをいれる。自分の場合はCube
    public GameObject Anker,AnkerPrefab;
    public GameObject AnkerLine, AnkerLinePrefab;

    public Camera PlayerCamera;
    public bool IsUsingAnker;
    public bool IsUsingInput;
    public bool IsMovingByAnker;
    //歩くはやさ
    float moveSpeed = 3f;
    //0.7秒くらいでアンカーの移動を終わらせたい
    float AnkerMoveSpeed = 50f;
    float AnkerDistance = 35f;

    private void Awake()
    {
        if(rigidBody == null)
        {
            rigidBody = GetComponent<Rigidbody>();
        }
        if(PlayerCamera == null)
        {
            PlayerCamera = GetComponentInChildren<Camera>();
        }
    }

    void Start()
    {
        IsUsingAnker = false;
        Anker = Instantiate(AnkerPrefab);
        Anker.SetActive(false);
        AnkerLine = Instantiate(AnkerLinePrefab);
        AnkerLine.SetActive(false);
    }

    void Update()
    {
        inputHorizontal = Input.GetAxisRaw("Horizontal");
        inputVertical = Input.GetAxisRaw("Vertical");
        if(inputVertical == 0 && inputHorizontal == 0)
        {
            IsUsingInput = false;
        }
        else
        {
            IsUsingInput = true;
        }
        if(Input.GetMouseButtonDown(0))
        {
            float distance = 100;
            float duration = 10;

            Ray ray = new Ray(transform.position,PlayerCamera.transform.forward.normalized);
            //インスペクタでRayを確認したい場合はしたのやつのコメントアウトをやめる
            //Debug.DrawRay(ray.origin, ray.direction * distance, Color.red, duration, false);

            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, distance))
            {
                if (IsUsingAnker == false)
                {
                    //始点がray.originじゃないとずれる
                    StartCoroutine(AnkerCoroutine(ray.origin,hit.point));
                }
            }
            else
            {
                if (IsUsingAnker == false)
                {
                    //始点がray.originじゃないとずれる
                    // ray.origin足さないとずれる
                    StartCoroutine(AnkerCoroutine(ray.origin,ray.direction * distance + ray.origin));
                }
            }
        }
    }

    void FixedUpdate()
    {
        // カメラの方向から、XZ平面の単位ベクトルをもとめる
        Vector3 cameraForward = Vector3.Scale(PlayerCamera.transform.forward, new Vector3(1, 0, 1)).normalized;
        Vector3 cameraSide = Vector3.Scale(PlayerCamera.transform.right, new Vector3(1, 0, 1)).normalized;
        // Inputとカメラの向きから移動方向と大きさをきめる
        Vector3 moveForward = cameraForward * inputVertical;
        Vector3 moveSide = cameraSide * inputHorizontal;

        // 移動方向にスピードを掛ける。落ちるときにふわふわしないために分岐している
        if(!IsMovingByAnker) 
        {
            rigidBody.velocity = rigidBody.velocity = (moveForward + moveSide) * moveSpeed + new Vector3(0,             rigidBody.velocity.y, 0);
        }
        else
        {
            rigidBody.velocity = rigidBody.velocity = (moveForward + moveSide) * moveSpeed;
        }
        // キャラクターの向きを進行方向に
        if (moveForward != Vector3.zero && inputVertical > 0)
        {
            transform.rotation = Quaternion.LookRotation(moveForward);
        }
        else if(moveForward != Vector3.zero && inputVertical < 0)
        {
            transform.rotation = Quaternion.LookRotation(-moveForward);
        }

        if(moveSide != Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(cameraForward);
        }

        if(moveForward == Vector3.zero && moveSide == Vector3.zero)
        {
            transform.rotation = Quaternion.LookRotation(cameraForward);
        }
    }

    private IEnumerator AnkerCoroutine(Vector3 firstPos,Vector3 target)
    {
        Anker.transform.position = firstPos;
        Anker.SetActive(true);
        AnkerLine.SetActive(true);
        float distance = 0f;
        while (distance < AnkerDistance && Anker.transform.position != target) 
        { 
            IsUsingAnker = true;
            float speed = Time.deltaTime * AnkerMoveSpeed; Anker.transform.position =          Vector3.MoveTowards(Anker.transform.position,target,speed);
            AnkerLine.transform.localScale = new Vector3(0.1f, 0.1f, distance);
            AnkerLine.transform.LookAt(target);
            //アンカーとプレイヤーの中点を座標にのびていく
            AnkerLine.transform.position = (Anker.transform.position + transform.position) * 0.5f;
            distance += speed;
            ield return null;
        }
        Anker.SetActive(false);
        AnkerLine.SetActive(false);
        StartCoroutine(AnkerMoveCoroutine());
        IsUsingAnker = false;
    }
    private IEnumerator AnkerMoveCoroutine() 
    {
        //重力等の関係でtransform.position != Anker.transform.positionにするとめっちゃぶれる
        while ((transform.position - Anker.transform.position).magnitude >= 0.5f && !IsUsingInput)
        {
            IsMovingByAnker = true;
            var heading = Anker.transform.position - transform.position;
            var distance = heading.magnitude;
            var direction = heading / distance;
            if(Anker.transform.position.y <= transform.position.y)
                {
                    direction = Vector3.Scale(direction, new Vector3(1, 0, 1));
                }
            float speed = Time.deltaTime * (AnkerMoveSpeed * 2f / moveSpeed);
            transform.position += direction * speed;
            yield return null;
        }
        IsMovingByAnker = false;
    }
}

PlayerCameraクラス
Playerの子オブジェクトにCameraと一緒につける。
AnkerLinePrefabを見たいのでカメラのtransformはyを2ぐらいにする。

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

public class PlayerCamera : MonoBehaviour
{
    public Transform VerticalRotation;
    public Transform HorizontalRotation;

    public float XRotation;
    public float YRotation;



    // Start is called before the first frame update
    private void Awake()
    {
        if(VerticalRotation == null)
        {
            VerticalRotation = transform.parent;
        }
        if(HorizontalRotation == null)
        {
            HorizontalRotation = GetComponent<Transform>();
        }

    }
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        XRotation = Input.GetAxis("Mouse X");
        YRotation = Input.GetAxis("Mouse Y");
        //ここをマイナスにするとマウスの上下と逆にカメラワークが動く
        VerticalRotation.transform.Rotate(0, XRotation, 0);
        //ここをプラスにするとマウスの左右と逆にカメラワークが動く
        HorizontalRotation.transform.Rotate(-YRotation, 0, 0);
    }
}

インデントがゴミ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA