Управление персонажа как в Lineage 2 , управление камерой L2

Общие вопросы о Unity3D

Управление персонажа как в Lineage 2 , управление камерой L2

Сообщение NCsoft 12 фев 2017, 00:02

Доброго времени суток !
Столкнулся с очень интересной проблемой которую не могу решить !

в общем решил сделать передвижение персонажа как в 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);
        }
    }
}
 

к стати , вдруг кому то и пригодится
управление камерой вокруг персонажа как в 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);
    }
}

 


затем импортирую карту FBX на которой присутствуют и горы и домики
закинул на сцену и в инспекторе в разделе Static установил всем объектам Navigation Static

Изображение

затем к объектам (карте) пришлось добавлять Box Collider потому что без него он не хотел ходить
в общем всё заработало , и персонаж начал нормально ходить и обходить дома и препятствия которые были запечены в Window Navigation

Изображение


а вот собственно сама проблема
персонаж не может нормально заходить на горку , и тупит в управление там где есть возвышенности или ямы
как оказалось управление опирается на BoxCollider , опустил его пониже и сделал по тоньше , вроде бы начал более менее , но всё равно тупит
когда я нажимаю на гору , он на неё забегает а потом пробегает и дальше бежит
размыслив я понял что наш рейкаст стреляет через горку то тех пор пока не упрётся в BoxCollider
то есть типа так

Изображение

на деле я смотрю с камеры и не вижу ту область куда получает navMeshAgent.SetDestination
я вижу только гору
сперва думал проблема в длине рейкаста но потом понял что он тут не причём
затем я решил сделать много BoxCollider и поставить их согласно траектории ланшафта из карты
ЭВРИКА ! заработало !

Изображение

но после того как я импортировал нормальный ланшафт тот что мне нужно , установил все здания , и начал устанавливать под каждую горку и под каждую ступеньку из замков
у меня количество BoxCollider превысило более 700 штук и начало жутко тормозить !
и я понял что я дибил и в пустую было потрачено 3 дня ...

в общем собственно вопрос : Можно ли как то BoxCollider изогнуть под ланшафт , потому что как мне показалось он может быть исключительно только квадратным ну или прямоугольным ...
ну или заставить слушать не BoxCollider а к примеру вот эту грань NavMesh

Изображение

я так понял она называется NavMesh так как когда я убираю галочку Show NavMesh , зелёное поле изчезает
вот только я не пойму как заставить персонажа - рейкаст передавать координаты которые упёрлись в NavMesh поле , а не в BoxCollider

благодарствую за затраченное время и за внимание !
~o)
Последний раз редактировалось NCsoft 12 фев 2017, 07:23, всего редактировалось 2 раз(а).
Аватара пользователя
NCsoft
UNIт
 
Сообщения: 147
Зарегистрирован: 14 мар 2014, 05:47
Откуда: Украина
Skype: GM_NCsoft

Re: Управление персонажа как в Lineage 2 , управление камерой L2

Сообщение Xtir 12 фев 2017, 00:45

Что мешает использовать MeshCollider?
Насчёт рэйкаста по навмеш - https://docs.unity3d.com/540/Documentation/ScriptReference/NavMesh.Raycast.html, думаю это то, что Вам нужно.
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37

Re: Управление персонажа как в Lineage 2 , управление камерой L2

Сообщение NCsoft 12 фев 2017, 02:58

Xtir писал(а):Что мешает использовать MeshCollider?

Вот это я даю ... как это я сразу не додумался за место BoxCollider использовать MeshCollider ...

Изображение

Xtir писал(а):Насчёт рэйкаста по навмеш - https://docs.unity3d.com/540/Documentation/ScriptReference/NavMesh.Raycast.html, думаю это то, что Вам нужно.

Просмотрел я то что Вы скинули
довольно интересная штука !
Но ...
у неё есть большой недостаток !

Изображение

Красным отмечена та позиция куда придёт персонаж если использовать Rays from the Camera
https://docs.unity3d.com/ru/520/Manual/CameraRays.html
(Собственно я его использовал в начале)

Зелёным отмечена та позиция куда придёт персонаж если использовать NavMesh.Raycast
https://docs.unity3d.com/540/Documentat ... ycast.html
(Именно то что Вы посоветовали)

Его недостаток в том что он не рассчитывает маршрут что бы обойти препятствие а просто берёт позицию ближайшего препятствия
между прочим очень хорошая вещь , пригодится для подземелья и катакомб что бы не вылетал игрок за карту
так как обычно такие локации находятся поверх основной , и рейкаст может случайно дострелить до внешнего мира и персонаж будет пытаться обойти , в этоге может пройти через объекты и начать падать до тех пор пока не упадёт на основной мир
(Это моё предположение конечно , о том как устроенна игровая вселенная и какие могут быть баги)

вот собственно код

что бы не обходил препятствия :
Синтаксис:
Используется csharp

    public NavMeshAgent navMeshAgent ;
    void Start()
    {
        navMeshAgent = GetComponent<NavMeshAgent>();
    }
    NavMeshHit navMeshHit;
    bool blocked;
    Ray ray;
    RaycastHit raycastHit;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Physics.Raycast(ray, out raycastHit, 256);
            blocked = NavMesh.Raycast(transform.position, raycastHit.point, out navMeshHit, NavMesh.AllAreas);
            {
                if (blocked) navMeshAgent.SetDestination(navMeshHit.position);
                else navMeshAgent.SetDestination(raycastHit.point);
            }
        }
    }
}
 


к стати есть ray = и blacke = вынести из if тогда будет обходить !
но очень часто останавливается возле препятствия и больше не слушает контролер

Приношу великий поклон и благодарю за помощь !
Аватара пользователя
NCsoft
UNIт
 
Сообщения: 147
Зарегистрирован: 14 мар 2014, 05:47
Откуда: Украина
Skype: GM_NCsoft


Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 6