Столкнулся с очень интересной проблемой которую не могу решить !
в общем решил сделать передвижение персонажа как в Lineage 2
по щелчку мышки , персонаж двигается в те координаты куда собственно был произведёт клик мышки
сделать это не составило труда , там всё просто
на Player вешаем NavMeshAgent и скрипт
Синтаксис:
Используется csharp
using UnityEngine;
using UnityEngine.AI;
public class controller : MonoBehaviour
{
NavMeshAgent navMeshAgent;
void Start()
{
navMeshAgent = GetComponent<NavMeshAgent>();
}
private void Update()
{
cameraRaycast();
}
void cameraRaycast()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 256) && Input.GetMouseButtonDown(0))
{
navMeshAgent.SetDestination(hit.point);
}
}
}
using UnityEngine.AI;
public class controller : MonoBehaviour
{
NavMeshAgent navMeshAgent;
void Start()
{
navMeshAgent = GetComponent<NavMeshAgent>();
}
private void Update()
{
cameraRaycast();
}
void cameraRaycast()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 256) && Input.GetMouseButtonDown(0))
{
navMeshAgent.SetDestination(hit.point);
}
}
}
к стати , вдруг кому то и пригодится
управление камерой вокруг персонажа как в Lineage 2
Вешается на камеру Player
правда добавил управление от стрелочек на клавиатуре , и повышение и понижение положения камеры при зажатом колёсике на мышке
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public Transform Player;
public float height = 1.53f;
public float heightMinimum = 0.25f;
public float heightMaximum = 1.75f;
public float heightSpeed = 1.0f;
public float distance = 4.0f;
public float distanceMaximum = 10.0f;
public float distanceMinimal = 0.5f;
public float inclineMaximum = 80.0f;
public float inclineMinimal = -40.0f;
public float speedHorizontal = 200.0f;
public float speedVertical = 200.0f;
public float speedZoom = 25;
private float x = 0.0f;
private float y = 0.0f;
public void Start()
{
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
if (GetComponent<Rigidbody>()) GetComponent<Rigidbody>().freezeRotation = true;
}
public void LateUpdate()
{
if (!Player) return;
if (Input.GetMouseButton(1))
{
x += Input.GetAxis("Mouse X") * speedHorizontal * 0.02f;
y -= Input.GetAxis("Mouse Y") * speedVertical * 0.02f;
}
else if (Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") != 0)
{
if (Input.GetKey(KeyCode.LeftArrow)) x += 0.7f * speedHorizontal * 0.02f;
if (Input.GetKey(KeyCode.RightArrow)) x -= 0.7f * speedHorizontal * 0.02f;
if (Input.GetKey(KeyCode.UpArrow)) y += 0.5f * speedVertical * 0.02f;
if (Input.GetKey(KeyCode.DownArrow)) y -= 0.5f * speedVertical * 0.02f;
}
if (Input.GetKey(KeyCode.Mouse2))
{
if (height >= heightMinimum && Input.GetAxis("Mouse Y") > 0 || height <= heightMaximum && Input.GetAxis("Mouse Y") < 0 || height >= heightMinimum && height <= heightMaximum) height -= Input.GetAxis("Mouse Y") * heightSpeed * 0.01f;
}
distance += (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * speedZoom * Mathf.Abs(distance);
distance = Mathf.Clamp(distance, distanceMinimal, distanceMaximum);
y = ClampAngle(y, inclineMinimal, inclineMaximum);
Quaternion rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation;
Vector3 position = Player.position - (rotation * Vector3.forward * distance + new Vector3(0, -height, 0));
transform.position = position;
RaycastHit hit;
Vector3 trueTargetPosition = Player.transform.position - new Vector3(0, -height, 0);
if (Physics.Linecast(trueTargetPosition, transform.position, out hit))
{
float tempDistance = Vector3.Distance(trueTargetPosition, hit.point) - 0.28f;
position = Player.position - (rotation * Vector3.forward * tempDistance + new Vector3(0, -height, 0));
transform.position = position;
}
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public Transform Player;
public float height = 1.53f;
public float heightMinimum = 0.25f;
public float heightMaximum = 1.75f;
public float heightSpeed = 1.0f;
public float distance = 4.0f;
public float distanceMaximum = 10.0f;
public float distanceMinimal = 0.5f;
public float inclineMaximum = 80.0f;
public float inclineMinimal = -40.0f;
public float speedHorizontal = 200.0f;
public float speedVertical = 200.0f;
public float speedZoom = 25;
private float x = 0.0f;
private float y = 0.0f;
public void Start()
{
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
if (GetComponent<Rigidbody>()) GetComponent<Rigidbody>().freezeRotation = true;
}
public void LateUpdate()
{
if (!Player) return;
if (Input.GetMouseButton(1))
{
x += Input.GetAxis("Mouse X") * speedHorizontal * 0.02f;
y -= Input.GetAxis("Mouse Y") * speedVertical * 0.02f;
}
else if (Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") != 0)
{
if (Input.GetKey(KeyCode.LeftArrow)) x += 0.7f * speedHorizontal * 0.02f;
if (Input.GetKey(KeyCode.RightArrow)) x -= 0.7f * speedHorizontal * 0.02f;
if (Input.GetKey(KeyCode.UpArrow)) y += 0.5f * speedVertical * 0.02f;
if (Input.GetKey(KeyCode.DownArrow)) y -= 0.5f * speedVertical * 0.02f;
}
if (Input.GetKey(KeyCode.Mouse2))
{
if (height >= heightMinimum && Input.GetAxis("Mouse Y") > 0 || height <= heightMaximum && Input.GetAxis("Mouse Y") < 0 || height >= heightMinimum && height <= heightMaximum) height -= Input.GetAxis("Mouse Y") * heightSpeed * 0.01f;
}
distance += (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * speedZoom * Mathf.Abs(distance);
distance = Mathf.Clamp(distance, distanceMinimal, distanceMaximum);
y = ClampAngle(y, inclineMinimal, inclineMaximum);
Quaternion rotation = Quaternion.Euler(y, x, 0);
transform.rotation = rotation;
Vector3 position = Player.position - (rotation * Vector3.forward * distance + new Vector3(0, -height, 0));
transform.position = position;
RaycastHit hit;
Vector3 trueTargetPosition = Player.transform.position - new Vector3(0, -height, 0);
if (Physics.Linecast(trueTargetPosition, transform.position, out hit))
{
float tempDistance = Vector3.Distance(trueTargetPosition, hit.point) - 0.28f;
position = Player.position - (rotation * Vector3.forward * tempDistance + new Vector3(0, -height, 0));
transform.position = position;
}
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
затем импортирую карту FBX на которой присутствуют и горы и домики
закинул на сцену и в инспекторе в разделе Static установил всем объектам Navigation Static
затем к объектам (карте) пришлось добавлять Box Collider потому что без него он не хотел ходить
в общем всё заработало , и персонаж начал нормально ходить и обходить дома и препятствия которые были запечены в Window Navigation
а вот собственно сама проблема
персонаж не может нормально заходить на горку , и тупит в управление там где есть возвышенности или ямы
как оказалось управление опирается на BoxCollider , опустил его пониже и сделал по тоньше , вроде бы начал более менее , но всё равно тупит
когда я нажимаю на гору , он на неё забегает а потом пробегает и дальше бежит
размыслив я понял что наш рейкаст стреляет через горку то тех пор пока не упрётся в BoxCollider
то есть типа так
на деле я смотрю с камеры и не вижу ту область куда получает navMeshAgent.SetDestination
я вижу только гору
сперва думал проблема в длине рейкаста но потом понял что он тут не причём
затем я решил сделать много BoxCollider и поставить их согласно траектории ланшафта из карты
ЭВРИКА ! заработало !
но после того как я импортировал нормальный ланшафт тот что мне нужно , установил все здания , и начал устанавливать под каждую горку и под каждую ступеньку из замков
у меня количество BoxCollider превысило более 700 штук и начало жутко тормозить !
и я понял что я дибил и в пустую было потрачено 3 дня ...
в общем собственно вопрос : Можно ли как то BoxCollider изогнуть под ланшафт , потому что как мне показалось он может быть исключительно только квадратным ну или прямоугольным ...
ну или заставить слушать не BoxCollider а к примеру вот эту грань NavMesh
я так понял она называется NavMesh так как когда я убираю галочку Show NavMesh , зелёное поле изчезает
вот только я не пойму как заставить персонажа - рейкаст передавать координаты которые упёрлись в NavMesh поле , а не в BoxCollider
благодарствую за затраченное время и за внимание !