forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Общие вопросы (http://forum.boolean.name/forumdisplay.php?f=166)
-   -   Вопросы от новичка (http://forum.boolean.name/showthread.php?t=15809)

WISHMASTER35 10.01.2012 00:24

Ответ: Вопросы от новичка
 
При рейкасте луч врезается в самого же игрока, который пустил луч. Если луч дальше отодвинуть от игрока, то может будет пропускать врагов, которые рядом(

pax 10.01.2012 00:34

Ответ: Вопросы от новичка
 
помести игрока в другой слой, стреляй во все, кроме этого слоя. С врагами можно поступить так же.

WISHMASTER35 10.01.2012 17:37

Ответ: Вопросы от новичка
 
А как в С# лучше такое сообщение передать объекту в который попал?
Хотел повесить на скрипт интерфейс, которому и передавать это сообщение, но GetComponent не хочет искать компонент с моим интерфейсом(
Хотя можно просто все скрипты объекта проверить на принадлежность интерфейсу и вызвать нужный метод в нужных объектах.

Aikon 10.01.2012 22:40

Ответ: Вопросы от новичка
 
WISHMASTER35, странно, что не ищет. Ты уверен, что компонент висит? Может в имени ошибка? Код в студию.

Расскажу про свой топорный метод решения схожей задачи:
1. Создаем класс
Код:

class RayReceiver  : MonoBehaviour {
        public virtual void OnRay()
        {
                // тут помещаем стандартный обработчик, например уничтожить объект
        }
}

Теперь допустим есть несколько разных классов, которые должны принимать сообщение о приходящем луче.
Тогда класс наследуем не от MonoBehaviour, а от RayRaceiver
Код:

class TestClass : RayReceiver  {
        // можно не писать, если устроит стандартный
        public override void OnRay()
        {
                // тут помещается обработчик, уникальный для класса. Позже можем вызвать родительский, если надо
        }
}

Где то в обработчиках нажатия
Код:

if (Input.GetMouseButtonDown(0))
{
        Ray ray = mlCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        if (!Physics.Raycast(ray, out hit))
                return;
        RayReceiver rr = hit.collider.gameObject.GetComponent<RayReceiver>();
        if (rr != null)
                rr.OnRay();
}

C# вроде запрещает множественное наследование, но поскольку у меня иерархия объектов простая, как и сама задача, то такое вот решение меня вполне устраивает.


P.S. Кстати нашел баг: допустим лежит кубик с RigidBody на другом c BoxCollider, то сообщение OnCollissionStay через некоторое время перестает приходить, пока кубику с RigidBody WakeUp() не сделать.

WISHMASTER35 10.01.2012 23:10

Ответ: Вопросы от новичка
 
Aikon, не совсем правильно ты делаешь. Для этого используются интерфейсы.
И если у тебя есть класс, который уже наследуется от друга твоего класса, то твой способ не сработает.

Я сделал интерфейс
Код:

public interface BulletReceiver {
        void Attacked(Vector3 point);
}

Могу добавить этот интерфейс любому скрипту.
А при выстреле делаю так:
Код:

                                MonoBehaviour[] components = hit.collider.gameObject.GetComponents<MonoBehaviour>();
                                foreach( MonoBehaviour component in components ) {
                                        if( component is BulletReceiver ) {
                                                ( ( BulletReceiver ) component ).Attacked( hit.point );
                                        }
                                }

GetComponents ищет все что унаследовано от Component, поэтому мой интерфейс и не искало. Вот только без поиска нельзя получить список всех скриптов?
Я вот только не понял в C# и родительские классы и интерфейсы пишутся через запятую после двоеточия? В java для наследования используется extends, а для интерфейсов implements.

Aikon 11.01.2012 00:10

Ответ: Вопросы от новичка
 
Цитата:

Я вот только не понял в C# и родительские классы и интерфейсы пишутся через запятую после двоеточия?
Цитата:

Как известно множественное наследование в таких языках как Java и С# отсутствует, т.к. является потенциальным источником ошибок. Вместо него разработчику предлагается использовать механизм интерфейсов.
Т.е. сначала пишем один базовый класс, если надо, потом через запятую далее необходимые интерфейсы сколько надо.

С классом да, налажал, забыл глянуть что есть интерфейсы. Переделал. У меня все проходит. Вот код

Интерфейс
Код:

public interface ITest {
        void echo(string text);
}

Компонента CTest, которая реализует интерфейс ITest.
Чтобы она могла быть найдена через GetComponent я так же отнаследовал ее от базового класса MonoBehaviour
Код:

using UnityEngine;
using System.Collections;

public class CTest : MonoBehaviour, ITest  {

        public void echo(string text)
        {
                Debug.Log(text);
        }
}

В пустом проекте на камеру повесил компонент CTest и общий компонент для теста
Код:

using UnityEngine;
using System.Collections;

public class Common : MonoBehaviour {
        void Start () {
                // Мне вот этот кривой перебор не нравится. Даже если для каждого объекта результат в член класса запихнуть.       
                foreach (MonoBehaviour mb in this.GetComponents<MonoBehaviour>())
                {
                        if (mb is ITest)
                                ((ITest)mb).echo("OK");
                }
        }
}


WISHMASTER35 11.01.2012 00:45

Ответ: Вопросы от новичка
 
Цитата:

Чтобы она могла быть найдена через GetComponent я так же отнаследовал ее от базового класса MonoBehaviour
Все равно ты ищешь по MonoBehaviour, а не по имени интерфейса.

А OnPostRender вызывается только у камеры? Нету методов, которые вызывались бы после рендеринга или перед Update?

Кстате, я так и не понял Raycast будет попадать в CharacterContoller? Ведь он сам использует CapsuleCast. Как тут быть?

Aikon 11.01.2012 00:58

Ответ: Вопросы от новичка
 
WISHMASTER35, т.е. ты хочешь выполнять поиск не компонентам и потом проверять у них наличие интерфейса, а выполнять поиск по наименованию интерфейса, отбирая компоненты, которые поддерживают его, а потом вызывать метод у тех компонент, где данный интерфейс реализован? Вроде теже яйца, только вид с боку и не факт, что поддерживается Unity (pax думаю придет напишет).

С главным циклов в Unity не все понятно. Т.е. если на сцену два кубика добавить и у каждого Update задать, то порядок вызовов этих Update-ов мне кажется заранее не будет известен, либо не стоит к нему привязываться.
Можно попробовать использовать LateUpdate (только для потомков MonoBehaviour) и FixedUpdate (только для физических тел).

WISHMASTER35 11.01.2012 01:34

Ответ: Вопросы от новичка
 
Aikon, да я же и писал, что GetComponent не ищет по имени интерфейса.
А зачем вообще нужно знать порядок вызовов Update?
У меня в Update у оружия вызывается метод принятия пули у врага. Я хочу в этом методе принятия пули сделать врага красным, а после одного рендеринга сделать его снова белым. Но как это сделать после того как отрендерился красный враг хз. По крайней мере без дополнительных переменных. А то можно в OnWillRender поднять флаг, что в следующем Update сделать врага снова белым.

pax 11.01.2012 02:17

Ответ: Вопросы от новичка
 
А не проще
PHP код:

hit.collider.gameObject.SendMessage("OnRay"SendMessageOptions.DontRequireReceiver); 

никакие интерфейсы не нужны. Просто реализуйте функцию где нужно.

WISHMASTER35 11.01.2012 19:54

Ответ: Вопросы от новичка
 
Жаль только через SendMessage не передать больше одного параметра(
А кто-нибудь делал GUI для разных экранов? Как его сделать, что бы нормально смотрелось? Настроил под свой размер, а на маленьком джойстик на пол экрана и даже сдвинуть его не куда. И можно получить плотность пикселей?

Lestar 11.01.2012 20:48

Ответ: Вопросы от новичка
 
Через Screen получить текущее разрешение экрана и исходя из него позиционировать. Мессаги медленная операция.

WISHMASTER35 11.01.2012 22:16

Ответ: Вопросы от новичка
 
Lestar, по ширине или длине экрана выравнивать? На планшетах не будет очень большими элементы? тут желательно плотность пикселей еще знать.

pax 11.01.2012 23:40

Ответ: Вопросы от новичка
 
если использовать ортогональную камеру и плейны, то высота ортогональной камеры выстанавливается в половину высоты экрана, если экран уменьшается, то плены остаются в том же масштабе относительно размеров экрана. Единственное можно скорректировать горизонтальную позицию немного. Интерфейс такой можно рендерить отдельной камерой.

WISHMASTER35 11.01.2012 23:58

Ответ: Вопросы от новичка
 
pax, т.е. рисовать не через GUI, а в 3д? Тогда еще сложнее будет т.к. все будет растягиваться в зависимости от соотношения сторон. Ну ладно как нибудь буду подстраивать размеры GUITexture.
Кстати, нет скрипта что-то типа GUITexture, только чтобы отслеживал нажатие мышкой\тачем на текстуру как GUI.Button? А то из-за такой мелочи свой скрипт создавать не очень хочется)


Часовой пояс GMT +4, время: 11:56.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot