スパイドローンの実装












スパイドローンモード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(AudioSource))]
public class PlayerController : MonoBehaviour
{
public float walkSpeed;
public float runSpeed;
private Vector3 movement;
private CharacterController characterController;
private AudioSource audioSource;
public GameObject FPSCamera;
private Vector3 moveDir = Vector3.zero;
private float gravity = 9.8f;
public float jumpPower;
public AudioClip jumpSound;
private float runStepLengthen = 0.7f;
private float stepInterval = 10f;
private float stepCycle;
private float nextStep;
private float speed;
private bool isWalking;
public AudioClip stepSound;
private Vector3 initialCameraPosition;
private float timer = 0;
private float bobbingSpeed = 10f;
private float walkBobbing = 0.04f;
private float runBobbing = 0.07f;
// ★追加(スパイドローン)
public GameObject spyDPrefab;
public Transform takeOffPoint;
public GameObject aim;
private GameObject spyD;
private Rigidbody spyRb;
private float spyTurnInputValue;
private enum State
{
Normal,
ThrowingHook,
FlyingPlayer,
// ★追加(スパイドローン)
SpyDMode
}
public float hookRange = 100f;
public Transform hookTargetMark;
public Transform hookShot;
private Vector3 hookPoint;
private float hookShotSize;
private State state;
private void Start()
{
characterController = GetComponent<CharacterController>();
audioSource = GetComponent<AudioSource>();
initialCameraPosition = FPSCamera.transform.localPosition;
state = State.Normal;
hookShot.gameObject.SetActive(false);
hookTargetMark.gameObject.SetActive(false);
}
private void Update()
{
switch(state)
{
default:
case State.Normal:
PlayerMove();
ProgressStepCycle(speed);
HeadBob();
HookStart();
// ★追加(スパイドローン)
// スパイドローンの起動はNormalモードで行うのでここに追加する。
StartingSpyD();
break;
case State.ThrowingHook:
HookThrow();
break;
case State.FlyingPlayer:
HookFlyingMovement();
break;
// ★追加(スパイドローン)
// スパイドローンの操縦は専用モードで行うのでモードを追加する。
case State.SpyDMode:
PlaySpyD();
break;
}
}
void PlayerMove()
{
float moveH = Input.GetAxis("Horizontal");
float moveV = Input.GetAxis("Vertical");
movement = new Vector3(moveH, 0, moveV);
Vector3 desiredMove = FPSCamera.transform.forward * movement.z + FPSCamera.transform.right * movement.x;
moveDir.x = desiredMove.x * 5f;
moveDir.z = desiredMove.z * 5f;
if (Input.GetKey(KeyCode.LeftShift))
{
characterController.Move(moveDir * Time.deltaTime * runSpeed);
isWalking = false;
speed = runSpeed;
}
else
{
characterController.Move(moveDir * Time.deltaTime * walkSpeed);
isWalking = true;
speed = walkSpeed;
}
if (characterController.isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
moveDir.y = jumpPower;
audioSource.clip = jumpSound;
audioSource.Play();
}
}
else
{
moveDir.y -= gravity * Time.deltaTime;
}
}
void PlayStepSound()
{
if (!characterController.isGrounded)
{
return;
}
audioSource.clip = stepSound;
audioSource.PlayOneShot(audioSource.clip);
}
void ProgressStepCycle(float speed)
{
if (characterController.velocity.sqrMagnitude > 0 && (movement.x != 0 || movement.z != 0))
{
stepCycle += (characterController.velocity.magnitude + (speed * (isWalking ? 1f : runStepLengthen))) * Time.deltaTime;
}
if (!(stepCycle > nextStep))
{
return;
}
nextStep = stepCycle + stepInterval;
PlayStepSound();
}
void HeadBob()
{
Vector3 newCameraPosition;
float bobbingAmount;
if (characterController.velocity.sqrMagnitude > 0 && (movement.x != 0 || movement.z != 0))
{
timer += (Time.deltaTime * bobbingSpeed);
bobbingAmount = isWalking ? walkBobbing : runBobbing;
FPSCamera.transform.localPosition = new Vector3(0, initialCameraPosition.y + Mathf.Sin(timer) * bobbingAmount, 0);
newCameraPosition = FPSCamera.transform.localPosition;
}
else
{
timer = 0;
newCameraPosition = FPSCamera.transform.localPosition;
}
FPSCamera.transform.localPosition = newCameraPosition;
}
void HookStart()
{
if(Input.GetMouseButtonDown(1))
{
RaycastHit hit;
if(Physics.Raycast(FPSCamera.transform.position, FPSCamera.transform.forward, out hit, hookRange))
{
hookTargetMark.position = hit.point;
hookPoint = hit.point;
state = State.ThrowingHook;
hookShotSize = 0f;
hookTargetMark.gameObject.SetActive(true);
hookShot.gameObject.SetActive(true);
}
}
}
void HookFlyingMovement()
{
Vector3 moveDir = (hookPoint - transform.position).normalized;
float flyingSpeed = Vector3.Distance(transform.position, hookPoint) * 2f;
characterController.Move(moveDir * flyingSpeed * Time.deltaTime);
if(Input.GetMouseButtonDown(1))
{
state = State.Normal;
hookTargetMark.gameObject.SetActive(false);
hookShot.gameObject.SetActive(false);
}
if(Vector3.Distance(transform.position, hookPoint) < 2f)
{
hookShot.gameObject.SetActive(false);
}
}
void HookThrow()
{
hookShot.LookAt(hookPoint);
float hookShotSpeed = 50f;
hookShotSize += hookShotSpeed * Time.deltaTime;
hookShot.localScale = new Vector3(1, 1, hookShotSize);
if(hookShotSize >= Vector3.Distance(transform.position, hookPoint))
{
state = State.FlyingPlayer;
}
}
// ★追加(スパイドローン)
void StartingSpyD()
{
if(Input.GetKeyDown(KeyCode.Q))
{
// スパイドローンを実体化する
// 位置はtakeOffPointに合わせる。
// 角度はPlayerに合わせる。
spyD = Instantiate(spyDPrefab, takeOffPoint.position, transform.rotation);
// 照準器をノンアクティブ状態にする
aim.SetActive(false);
// スパイドローン操縦モードに切り替える
state = State.SpyDMode;
}
}
// ★追加(スパイドローン)
void PlaySpyD()
{
if(spyD != null)
{
spyRb = spyD.GetComponent<Rigidbody>();
// 手動旋回
spyTurnInputValue = Input.GetAxis("Horizontal");
float turn = spyTurnInputValue * 100 * Time.deltaTime;
Quaternion turnRotation = Quaternion.Euler(0, turn, 0);
spyRb.MoveRotation(spyRb.rotation * turnRotation);
}
// 手動高度調整
if(Input.GetKey(KeyCode.W))
{
spyD.transform.Translate(0, 0.1f, 0);
}
if(Input.GetKey(KeyCode.S))
{
spyD.transform.Translate(0, -0.1f, 0);
}
}
// ★追加(スパイドローン)
// ノーマルモードに戻すためのメソッド
// このメソッドは、SpyDスクリプトの中から実行する(ポイント)
// publicが必須
public void StopSpyD()
{
state = State.Normal;
// 照準器をアクティブ状態にする。
aim.SetActive(true);
}
}

スパイドローン
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpyD : MonoBehaviour
{
public GameObject effectPrefab;
public AudioClip sound;
public float moveSpeed = 100f;
private Rigidbody rb;
private float passTime;
private PlayerController pc;
void Start()
{
rb = GetComponent<Rigidbody>();
pc = GameObject.Find("Player").GetComponent<PlayerController>();
}
void Update()
{
// 自動前進
// 徐々に速度が上がる
passTime += Time.deltaTime;
rb.velocity = transform.forward * (moveSpeed * passTime) * Time.deltaTime;
}
private void OnCollisionEnter(Collision collision)
{
// プレーヤーをNormalモードに戻す。
pc.StopSpyD();
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 1.0f);
AudioSource.PlayClipAtPoint(sound, Camera.main.transform.position);
// 0.1秒後にドローンを破壊する。
Destroy(gameObject, 0.1f);
}
}








【2019版】X_Mission(基礎/全51回)
他のコースを見る











スパイドローンモード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
[RequireComponent(typeof(AudioSource))]
public class PlayerController : MonoBehaviour
{
public float walkSpeed;
public float runSpeed;
private Vector3 movement;
private CharacterController characterController;
private AudioSource audioSource;
public GameObject FPSCamera;
private Vector3 moveDir = Vector3.zero;
private float gravity = 9.8f;
public float jumpPower;
public AudioClip jumpSound;
private float runStepLengthen = 0.7f;
private float stepInterval = 10f;
private float stepCycle;
private float nextStep;
private float speed;
private bool isWalking;
public AudioClip stepSound;
private Vector3 initialCameraPosition;
private float timer = 0;
private float bobbingSpeed = 10f;
private float walkBobbing = 0.04f;
private float runBobbing = 0.07f;
// ★追加(スパイドローン)
public GameObject spyDPrefab;
public Transform takeOffPoint;
public GameObject aim;
private GameObject spyD;
private Rigidbody spyRb;
private float spyTurnInputValue;
private enum State
{
Normal,
ThrowingHook,
FlyingPlayer,
// ★追加(スパイドローン)
SpyDMode
}
public float hookRange = 100f;
public Transform hookTargetMark;
public Transform hookShot;
private Vector3 hookPoint;
private float hookShotSize;
private State state;
private void Start()
{
characterController = GetComponent<CharacterController>();
audioSource = GetComponent<AudioSource>();
initialCameraPosition = FPSCamera.transform.localPosition;
state = State.Normal;
hookShot.gameObject.SetActive(false);
hookTargetMark.gameObject.SetActive(false);
}
private void Update()
{
switch(state)
{
default:
case State.Normal:
PlayerMove();
ProgressStepCycle(speed);
HeadBob();
HookStart();
// ★追加(スパイドローン)
// スパイドローンの起動はNormalモードで行うのでここに追加する。
StartingSpyD();
break;
case State.ThrowingHook:
HookThrow();
break;
case State.FlyingPlayer:
HookFlyingMovement();
break;
// ★追加(スパイドローン)
// スパイドローンの操縦は専用モードで行うのでモードを追加する。
case State.SpyDMode:
PlaySpyD();
break;
}
}
void PlayerMove()
{
float moveH = Input.GetAxis("Horizontal");
float moveV = Input.GetAxis("Vertical");
movement = new Vector3(moveH, 0, moveV);
Vector3 desiredMove = FPSCamera.transform.forward * movement.z + FPSCamera.transform.right * movement.x;
moveDir.x = desiredMove.x * 5f;
moveDir.z = desiredMove.z * 5f;
if (Input.GetKey(KeyCode.LeftShift))
{
characterController.Move(moveDir * Time.deltaTime * runSpeed);
isWalking = false;
speed = runSpeed;
}
else
{
characterController.Move(moveDir * Time.deltaTime * walkSpeed);
isWalking = true;
speed = walkSpeed;
}
if (characterController.isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
moveDir.y = jumpPower;
audioSource.clip = jumpSound;
audioSource.Play();
}
}
else
{
moveDir.y -= gravity * Time.deltaTime;
}
}
void PlayStepSound()
{
if (!characterController.isGrounded)
{
return;
}
audioSource.clip = stepSound;
audioSource.PlayOneShot(audioSource.clip);
}
void ProgressStepCycle(float speed)
{
if (characterController.velocity.sqrMagnitude > 0 && (movement.x != 0 || movement.z != 0))
{
stepCycle += (characterController.velocity.magnitude + (speed * (isWalking ? 1f : runStepLengthen))) * Time.deltaTime;
}
if (!(stepCycle > nextStep))
{
return;
}
nextStep = stepCycle + stepInterval;
PlayStepSound();
}
void HeadBob()
{
Vector3 newCameraPosition;
float bobbingAmount;
if (characterController.velocity.sqrMagnitude > 0 && (movement.x != 0 || movement.z != 0))
{
timer += (Time.deltaTime * bobbingSpeed);
bobbingAmount = isWalking ? walkBobbing : runBobbing;
FPSCamera.transform.localPosition = new Vector3(0, initialCameraPosition.y + Mathf.Sin(timer) * bobbingAmount, 0);
newCameraPosition = FPSCamera.transform.localPosition;
}
else
{
timer = 0;
newCameraPosition = FPSCamera.transform.localPosition;
}
FPSCamera.transform.localPosition = newCameraPosition;
}
void HookStart()
{
if(Input.GetMouseButtonDown(1))
{
RaycastHit hit;
if(Physics.Raycast(FPSCamera.transform.position, FPSCamera.transform.forward, out hit, hookRange))
{
hookTargetMark.position = hit.point;
hookPoint = hit.point;
state = State.ThrowingHook;
hookShotSize = 0f;
hookTargetMark.gameObject.SetActive(true);
hookShot.gameObject.SetActive(true);
}
}
}
void HookFlyingMovement()
{
Vector3 moveDir = (hookPoint - transform.position).normalized;
float flyingSpeed = Vector3.Distance(transform.position, hookPoint) * 2f;
characterController.Move(moveDir * flyingSpeed * Time.deltaTime);
if(Input.GetMouseButtonDown(1))
{
state = State.Normal;
hookTargetMark.gameObject.SetActive(false);
hookShot.gameObject.SetActive(false);
}
if(Vector3.Distance(transform.position, hookPoint) < 2f)
{
hookShot.gameObject.SetActive(false);
}
}
void HookThrow()
{
hookShot.LookAt(hookPoint);
float hookShotSpeed = 50f;
hookShotSize += hookShotSpeed * Time.deltaTime;
hookShot.localScale = new Vector3(1, 1, hookShotSize);
if(hookShotSize >= Vector3.Distance(transform.position, hookPoint))
{
state = State.FlyingPlayer;
}
}
// ★追加(スパイドローン)
void StartingSpyD()
{
if(Input.GetKeyDown(KeyCode.Q))
{
// スパイドローンを実体化する
// 位置はtakeOffPointに合わせる。
// 角度はPlayerに合わせる。
spyD = Instantiate(spyDPrefab, takeOffPoint.position, transform.rotation);
// 照準器をノンアクティブ状態にする
aim.SetActive(false);
// スパイドローン操縦モードに切り替える
state = State.SpyDMode;
}
}
// ★追加(スパイドローン)
void PlaySpyD()
{
if(spyD != null)
{
spyRb = spyD.GetComponent<Rigidbody>();
// 手動旋回
spyTurnInputValue = Input.GetAxis("Horizontal");
float turn = spyTurnInputValue * 100 * Time.deltaTime;
Quaternion turnRotation = Quaternion.Euler(0, turn, 0);
spyRb.MoveRotation(spyRb.rotation * turnRotation);
}
// 手動高度調整
if(Input.GetKey(KeyCode.W))
{
spyD.transform.Translate(0, 0.1f, 0);
}
if(Input.GetKey(KeyCode.S))
{
spyD.transform.Translate(0, -0.1f, 0);
}
}
// ★追加(スパイドローン)
// ノーマルモードに戻すためのメソッド
// このメソッドは、SpyDスクリプトの中から実行する(ポイント)
// publicが必須
public void StopSpyD()
{
state = State.Normal;
// 照準器をアクティブ状態にする。
aim.SetActive(true);
}
}

スパイドローン
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpyD : MonoBehaviour
{
public GameObject effectPrefab;
public AudioClip sound;
public float moveSpeed = 100f;
private Rigidbody rb;
private float passTime;
private PlayerController pc;
void Start()
{
rb = GetComponent<Rigidbody>();
pc = GameObject.Find("Player").GetComponent<PlayerController>();
}
void Update()
{
// 自動前進
// 徐々に速度が上がる
passTime += Time.deltaTime;
rb.velocity = transform.forward * (moveSpeed * passTime) * Time.deltaTime;
}
private void OnCollisionEnter(Collision collision)
{
// プレーヤーをNormalモードに戻す。
pc.StopSpyD();
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 1.0f);
AudioSource.PlayClipAtPoint(sound, Camera.main.transform.position);
// 0.1秒後にドローンを破壊する。
Destroy(gameObject, 0.1f);
}
}








スパイドローンの実装