Unityでワイヤーアクション作りたい。立体機動風メモ

なにかあればTwitterにお願いします。
Twitter:ritz_prgrm
こちらにコメントしていただけると嬉しいですが、反応できるかわからないのとハードルが高いと思います。
Player
-PlayerCamera(Camera)
-AnchorPosition1(Empty)
-AnchorPosition2(Empty)
PlayerにはRigidbodyをアタッチ。
Dragは0、AngularDragは0、UseGravityオン、IsKinematicオフ、FreezeRotation全てオン。
AnchorPrefabはCube
TransformのScaleをすべて0.1
Rigidbodyをアタッチ。
Dragは0、AngularDragは0、UseGravityオフ、IsKinematicはオフ。
AnchorPrefabはCube。デフォルト。

Playerの
AnchorPoint1にAnchorPosition1をあてる。
AnchorPoint2にAnchorPosition2をあてる。

Player3DManeuverGearクラス

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player3DManeuverGear : MonoBehaviour
{
public float inputHorizontal;
public float inputVertical;
public Rigidbody rigidBody;
public Transform AnchorPoint1, AnchorPoint2;
private Vector3 Target;
public GameObject Anchor1,Anchor2, AnchorPrefab;
public GameObject AnchorLine1,AnchorLine2, AnchorLinePrefab;
public Camera PlayerCamera;
public SpringJoint Spring1, Spring2;
public bool IsUsingAnchor;
public bool IsUsingInput;
public bool IsMovingByAnchor;
public bool IsStayingInAir;
public bool IsOnGround;
float moveSpeed = 3f;
//0.7秒くらいでアンカーの移動を終わらせたい
float AnchorMoveSpeed = 50f;
float AnchorDistance = 35f;
private void Awake()
{
if (rigidBody == null)
{
rigidBody = GetComponentInParent();
}
if (PlayerCamera == null)
{
PlayerCamera = GetComponentInChildren();
}
}
// Start is called before the first frame update
void Start()
{
IsUsingAnchor = false;
Anchor1 = Instantiate(AnchorPrefab);
Anchor2 = Instantiate(AnchorPrefab);
Anchor1.SetActive(false);
Anchor2.SetActive(false);
AnchorLine1 = Instantiate(AnchorLinePrefab);
AnchorLine2 = Instantiate(AnchorLinePrefab);
AnchorLine1.SetActive(false);
AnchorLine2.SetActive(false);
}
// Update is called once per frame
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; // 飛ばす、表示するRayの長さ
float duration = 10;   // 表示時間(秒)
Ray ray = new Ray(transform.position, PlayerCamera.transform.forward.normalized);
//有効かするとScene画面で見える
Debug.DrawRay(ray.origin, ray.direction * distance, Color.red, duration, false);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, distance))
{
//pos = ray.direction * hit.distance;
//target = pos + ray.origin;
if (IsUsingAnchor == false)
{
//始点がray.originじゃないとずれる
StartCoroutine(AnchorCoroutine(ray.origin, hit.point));
}
Debug.Log("HitPoint =" + hit.point);
Debug.Log(hit.collider.gameObject.name);
}
else
{
if (IsUsingAnchor == false)
{
//始点がray.originじゃないとずれる
// ray.origin足さないとずれる
StartCoroutine(AnchorCoroutine(ray.origin, ray.direction * distance + ray.origin));
}
}
Debug.Log("RayDirection:" + ray.direction + "Ray:" + ray.direction * distance);
}
}
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;
// 方向キーの入力値とカメラの向きから移動方向を決定
Vector3 moveForward = cameraForward * inputVertical;
Vector3 moveSide = cameraSide * inputHorizontal;
// 移動方向にスピードを掛ける。落ちるときにふわふわしないために分岐
if (!IsMovingByAnchor)
{
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 void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Floor")
{
IsOnGround = true;
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.tag == "Floor")
{
IsOnGround = false;
}
}
private IEnumerator AnchorCoroutine(Vector3 firstPos, Vector3 target)
{
Target = target;
//Playerに対する相対的な位置を足す
Anchor1.transform.position = AnchorPoint1.transform.position;
Anchor2.transform.position = AnchorPoint2.transform.position;
var Anchor1Target = target + AnchorPoint1.transform.position - transform.position;
var Anchor2Target = target + AnchorPoint2.transform.position - transform.position;
Anchor1.SetActive(true);
Anchor2.SetActive(true);
AnchorLine1.SetActive(true);
AnchorLine2.SetActive(true);
float distance = 0f;
while (distance < AnchorDistance && (Anchor1.transform.position != Anchor1Target || Anchor2.transform.position != Anchor2.transform.position))
{
IsUsingAnchor = true; float speed = Time.deltaTime * AnchorMoveSpeed; Anchor1.transform.position = Vector3.MoveTowards(Anchor1.transform.position, Anchor1Target, speed);
Anchor2.transform.position = Vector3.MoveTowards(Anchor2.transform.position, Anchor2Target, speed);             
SetLine(AnchorLine1, Anchor1.transform.position, AnchorPoint1.transform.position, 0.1f);
SetLine(AnchorLine2, Anchor2.transform.position, AnchorPoint2.transform.position, 0.1f); distance += speed;
Debug.Log("target:" + target + "Anchor1Target:" + Anchor1Target + "Anchor2Target:" + Anchor2Target);             
//Line.SetPositions(new Vector3[] { transform.position, Anchor.transform.position }); 
//Debug.Log(Anchor.transform.position); yield return null;
}
StartCoroutine(AnchorMoveCoroutine()); 
IsUsingAnchor = false;
}
private IEnumerator AnchorMoveCoroutine()
{
//重力等の関係でtransform.position != Anchor.transform.positionにするとめっちゃぶれる
while ((transform.position - Target).magnitude >= 0.5f && !IsUsingInput)
{
IsMovingByAnchor = true;
var heading = Target - transform.position;
var distance = heading.magnitude;
var direction = heading / distance;
if (Target.y <= transform.position.y && IsOnGround)
{
direction = Vector3.Scale(direction, new Vector3(1, 0, 1));
}
float speed = Time.deltaTime * (AnchorMoveSpeed * 2f / moveSpeed);
SetLine(AnchorLine1, Anchor1.transform.position, AnchorPoint1.transform.position, 0.1f);         
SetLine(AnchorLine2, Anchor2.transform.position, AnchorPoint2.transform.position, 0.1f);
transform.position = Vector3.MoveTowards(transform.position, Target, speed);
if (!IsOnGround) 
{
if (Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(AnchorStayCoroutine());
IsMovingByAnchor = false; yield break;
}
}
yield return null;
}
Anchor1.SetActive(false);
Anchor2.SetActive(false);
AnchorLine1.SetActive(false);
AnchorLine2.SetActive(false);
IsMovingByAnchor = false;
}
private IEnumerator AnchorStayCoroutine()
{ //アンカーのしたにぶらさがりたいので新たに座標を設定
Vector3 UnderAnchorPosition = (Anchor1.transform.position + Anchor2.transform.position) * 0.5f - new Vector3(0, 3f, 0);
while (!IsUsingInput)
{
IsStayingInAir = true;
var heading = UnderAnchorPosition - transform.position;
var distance = heading.magnitude;
var direction = heading / distance;
float speed = Time.deltaTime * (AnchorMoveSpeed / moveSpeed);
if (distance > 3f && !GetComponent())
{
transform.position = Vector3.MoveTowards(transform.position, UnderAnchorPosition, speed);
Debug.Log(transform.position);
}
else if (distance == 3f && !GetComponent())
{
Debug.Log("velocity = 0");
rigidBody.velocity = Vector3.zero;
rigidBody.angularVelocity = Vector3.zero;
}
else
{
if (!GetComponent())
{
Debug.Log("No SpringJoint");
gameObject.AddComponent();
gameObject.AddComponent();
Spring1 = GetComponents()[0];
Spring2 = GetComponents()[1];
Spring1.connectedBody = Anchor1.GetComponent();
Spring2.connectedBody = Anchor2.GetComponent();
Spring1.autoConfigureConnectedAnchor = Spring2.autoConfigureConnectedAnchor = false;
Spring1.spring = Spring2.spring = 1f;
Spring1.connectedAnchor = Spring2.connectedAnchor = new Vector3(0f, 30f, 0f);
Spring1.minDistance = Spring2.minDistance = 3f;
Spring1.maxDistance = Spring2.maxDistance = 3f;
}
Anchor1.GetComponent().isKinematic = true;
Anchor2.GetComponent().isKinematic = true;
}
SetLine(AnchorLine1, Anchor1.transform.position, AnchorPoint1.transform.position, 0.1f);
SetLine(AnchorLine2, Anchor2.transform.position, AnchorPoint2.transform.position, 0.1f);
yield return null;
}
Destroy(GetComponents()[0]);
Destroy(GetComponents()[1]);
Anchor1.GetComponent().isKinematic = false;
Anchor2.GetComponent().isKinematic = false;
Anchor1.SetActive(false);
Anchor2.SetActive(false);
AnchorLine1.SetActive(false);
AnchorLine2.SetActive(false);
IsStayingInAir = false;
yield break;
}
private void SetLine(GameObject Line, Vector3 goal,Vector3 start,float size)
{
Line.transform.localScale = new Vector3(size, size, (goal - start).magnitude);
Line.transform.position = (goal + start) * 0.5f;
Line.transform.LookAt(goal);
}
}

PlayerCameraクラス

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();
}
}
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);
}
}

PlayerにふたつSpringJointをふたつつけていい感じにしたかった。
SpringJointを完全にひもにするにはどうすればいいのかわからない。

コメントを残す

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

CAPTCHA