forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Общие вопросы (http://forum.boolean.name/forumdisplay.php?f=166)
-   -   Проблемы разработки от EvilOkta (http://forum.boolean.name/showthread.php?t=17911)

EvilOkta 20.02.2013 12:58

Проблемы разработки от EvilOkta
 
Всем привет, не уверен что меня помнят ибо почти 4 (или больше?) года отсутствовал на форуме, возможно что-то поменялось.
Решил воскресить свой заброшенный на Blitz 3d проект и как площадку для реализации выбрал Unity, изучаю сейчас C#.

Такой вопрос, предположим в скрипте есть метод, в процессе выполнения которого анализируется некоторая ситуация и по результатам анализа выбирается одна из некоторых переменных, назовем их условно intA, intB, intC, intD. Пусть на момент окончания анализа они имеют значения 10, 20, 30, 40 соответственно.

Задача передать одну выбранную анализатором переменную в другой метод (предположим анализатор выбрал для обработки переменную intB ) и по выполнению другого метода вернуть значение выбранной переменной увеличенное на 5 (для примера).

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

Надеюсь пнете в нужном направлении ))

pax 20.02.2013 13:21

Ответ: Передача переменной в метод
 
Так? Или я не понял что ты хочешь?
PHP код:

public class MyIntUpdater:MonoBehaviour
{
    public 
int intA 10;
    public 
int intB 20;
    public 
int intC 30;
    public 
int intD 40;

    private 
void UpdateMyInt(ref int intVar)
    {
        
intVar+=5;
    }
 
    public 
void Update()
    {
         switch(
Random.Range(0,4))
         {
              case 
0:
                  
UpdateMyInt(ref intA);
                  break;
              case 
1:
                  
UpdateMyInt(ref intB);
                  break;
              case 
2:
                  
UpdateMyInt(ref intC);
                  break;
              case 
3:
                  
UpdateMyInt(ref intD);
                  break;
         }
    }




EvilOkta 20.02.2013 15:20

Ответ: Передача переменной в метод
 
Да, это как раз и интересовало, а как одновременно передавать в метод несколько таких параметров, есть способ?
т.е. пеердавать, скажем, intA для одной цели, а IntB для другой но ествественно за один вызов. С помощью ref есть возможность?

Я правильно понял логику:
PHP код:

public class MyIntUpdater:MonoBehaviour
{
    public 
int intA 10;
    public 
int intB 20;
    public 
int intC 30;
    public 
int intD 40;
    public 
int SetParam1SetParam2;
    public 
int param1param2;

    private 
void UpdateMyInt(ref int intVar1ref int ntVar2)
    {
        
intVar1+=5;
        
intVar2++;
        
SetParam1 SetParam2 0;
    }
 
    public 
void Update()
    {
         if (
SetParam == 0
         {
         
SetParam1 Random.Range(0,4);
         switch (
SetParam1)
              {
              case 
0:
                  
param1 intA;
                  break;
              case 
1:
                  
param1 intB;
                  break;
              case 
2:
                  
param1 intC;
                  break;
              case 
3:
                  
param1 intD;
                  break;
              }
         }

         
SetParam2 Random.Range(0,4);

         if (
SetParam1 != SetParam2)
         {
         switch(
SetParam2)
            {
              case 
0:
                  
param2 intA;
                  break;
              case 
1:
                  
param2 intB;
                  break;
              case 
2:
                  
param2 intC;
                  break;
              case 
3:
                  
param2 intD;
                  break;
             }
         }
         
         if (
SetParam1 != 0) & (SetParam2 !=0UpdateMyInt(ref param1ref param2);
    }



Такая конструкция будет работать? Или в синтаксисе с ref напутал?

pax 20.02.2013 15:42

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

EvilOkta 20.02.2013 15:59

Ответ: Передача переменной в метод
 
точно, я не учел что передаются другие переменные. Но сам синтаксис передачи - правильный?

или надо:
PHP код:

if (SetParam1 != 0) & (SetParam2 !=0UpdateMyInt(ref param1param2); //вот эта часть 

мне механизм передачи интересен из-за недопонимания синтаксиса

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

pax 20.02.2013 16:03

Ответ: Передача переменной в метод
 
про ref можно почитать тут

EvilOkta 20.02.2013 16:19

Ответ: Передача переменной в метод
 
спасибо, сегодня попробую поэксперементировать, как я понял из справки с помощью ref можно передавать не только переменную но и класс? или конкретный экземпляр класса?

pax 20.02.2013 16:20

Ответ: Передача переменной в метод
 
экземпляр, класс можно передавать через шаблон http://msdn.microsoft.com/ru-ru/library/512aeb7t.aspx

EvilOkta 20.02.2013 16:31

Ответ: Передача переменной в метод
 
здорово, мне кажется как раз то что нужно для реализации моей задачи, еще раз спасибо. Универсальный шаблон мне пока рановато, а передача экземпляра класса в связке с ref решит мою проблему.

p.s. надеюсь дело пойдет, а то пока не могу абстрагироваться от модели разработки блитца к модели ООП

pax 20.02.2013 16:44

Ответ: Передача переменной в метод
 
Собственно если передать экземпляр класса, то можно его поля менять. Т.к. это ссылочный тип. Нельзя менять поля у структур (типов значений - ValueType), их надо передавать с помощью ref.

EvilOkta 20.02.2013 16:51

Ответ: Передача переменной в метод
 
значит я для передачи параметров в метод могу сделать класс в котором перечислю все возможные параметры, которые можно передавать в метод (они после этого станут полями класса, правильно?). После блока-анализатора я создаю экземпляр класса в котором заполняю поля необходимыми для передачи параметрами, остальным например проставляю метки "без изменения" (образно выражаясь), в методе обработчике обрабатываю экземпляр класса - возвращаю в исходный метод и там выполняю замещение тех параметров которые требуются используя как донор измененный экземпляр класса (игнорируя параметры с метками), после этого уничтожаю экземпляр класса и скрипт возвращается к исходной точке. Верно мыслю?

pax 20.02.2013 16:55

Ответ: Передача переменной в метод
 
Ну я бы не стал создавать экземпляры каждый раз, иначе будет работать сборщик мусора. Можно сделать один такой объект и его переиспользовать.

Вообще я не смог представить задачу, в которой это все необходимо в такой форме) Вероятно есть решение проще...

EvilOkta 20.02.2013 17:11

Ответ: Передача переменной в метод
 
хочу просто оптимизировать управление юнитом, у меня в зависимости от команды (управление нестандартное, стратегически ориентированное, поэтому передвижением юнита будет управлять скрипт а не банальные WSAD) передаются (разными способами) параметры "маршрута" и "действий" по которым должен передвигаться юнит. Сам скрипт передвижение унифицирован и в зависимости от поступающих команд двигает юнит определенным образом.

Я понимаю что это все прекрасно реализуется огородом if..else но не хочу, понимаю что можно сделать оптимизацию и хочу ее натйти чтобы в перспективе использовать полученный опыт для других скриптов.

pax 20.02.2013 17:26

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

seaman 20.02.2013 17:35

Ответ: Передача переменной в метод
 
Цитата:

универсальное решение для разного количества переменных
Код:

public int Check(params int[] inp)
{
    int ret = 0;
    foreach(int j in inp)
    {
        if(j = 0) return ret;
        ret++;
    }
    return -1;
}

используем:
Цитата:

int a = Check(1, 2, 0);
int b = Check(0, 5, 7, 6, 4, 9);
int c = Check(8, 5);
Получим:
Код:

a = 2
b = 0
c = -1


pax 20.02.2013 17:37

Ответ: Передача переменной в метод
 
seaman ты передаешь числа, а надо передавать переменные и их менять. В params по ref не передать. И так как надо делать это для разного количества - достаточно простого массива, а не params, потому что не будешь же ты для каждого случая вызывать свою версию метода - то от чего хочет отказаться EvilOkta

seaman 20.02.2013 17:41

Ответ: Передача переменной в метод
 
А вернуть IEnumerable можно. Типа:
Код:

int[]Check(params int[] inp)
{
    int[] ret = new int[inp.Length];
    //делаем что надо со входными значениями и заносим их в ret
    return ret;
}

int[] aA = Check(a, b, c);
int[] bA = Check(b, c);

pax 20.02.2013 17:46

Ответ: Передача переменной в метод
 
Проблема не в этом. Проблема в том, что ему надо будет вызывать метод различными способами (с различным числом параметров), а это не нужно.

Я вообще его не очень понял, почему например для каждого найденного значения не вызвать функцию один раз, зачем в нее передавать все что надо обработать...

seaman 20.02.2013 17:48

Ответ: Передача переменной в метод
 
Ну я тоже не очень понял обсуждения. Просто привел пример как передавать разное число параметров в одну функцию.

EvilOkta 21.02.2013 10:30

Ответ: Передача переменной в метод
 
наверное слишком сумбурно объяснил, задача так поставлена потому что юнитом через этот скрипт планируется управлять как игроком так и ИИ.
Вообще при малом количестве параметров действительно подойдет switch/case.
Сейчас попробую поподробнее объяснить, возможно и правда проблема в том что я слишком все осложняю.

Игра пошаговая (типа incubation) юнит передвигается по квадратному полю с помощью одного и того же метода. Команда на направление движения устанавливает центр привязки юнита, вокруг которого он "перекатывается" на соседнее поле.
Есть две переменные отвечающие за его текущий поворот, имеется ввиду не физический поворот, а некоторые значения которые меняются при перемещении (это краеугольная концепция игры). При перемещении в одну сторону меняется одна переменная, в другую вторая и т.п.
Задача при инициализации движения передавать в метод именно ту переменную которую требуется обработать и вернуть ее измененное значение. При расширении скрипта (и написании ИИ) возникнет необходимость передавать и другие параметры для изменения. Так как игра тактического характера то при разном расположении и повороте юнита он будет иметь разные тактические параметры - это я и хотел реализовать в обработчике движения.
Если управляет игрок то довольно просто - он мышкой прокладывает маршрут по полю, анализатор запаковывает маршрут в команду, понятную методу перемещения и метод начинает перемещать юнит по маршруту, попутно изменяя его текущие параметры.
Если юнитом управляет ИИ, то до прокладки маршрута в действие вступате блок логики, анализирующий текущую ситуацию на поле, параметры и расположение юнитов и т.п. (тут кстати в этом блоке мне тоже бы пригодилась методика передачи/приема переменных или аналоги), и этот блок логики по результатам анализа так же формирует маршрут и отдает его методу перемещения.

Еще один момент, помимо перемещения юнита метод так же управляет его активными действиями, т.е. например "атака", "защита" и т.п. (образно говорю), поэтому и стоит задача унификация метода и отделение его от метода прокладки маршрута/действий.

Кстати насчет интерфейсов, немного не понял идею, это как?

pax 21.02.2013 11:10

Ответ: Передача переменной в метод
 
PHP код:

public interface IControlableByLogic
{
    
int parameter{getset;}
}

public class 
UserMonoBehaviourIControlableByLogic
{
    public 
int myControlableParameter

    
public parameter
    
{
        
get{ return myControlableParameter; }
        
setmyControlableParameter value;}
    }
    
}

public class 
AIMonoBehaviourIControlableByLogic
{
    public 
int myControlableParameterByAI

    
public parameter
    
{
        
get{ return myControlableParameterByAI; }
        
setmyControlableParameterByAI value;}
    }
}

public class  
GameLogicMonoBehaviour
{
   public 
void MoveUnit(IControlableByLogic unit)
   {
       
unit.parameter += 1;
   }


Собственно вместо интерфейсов можно использовать наследование - унаследовать базовый класc Unit от MonoBehaviour, дать ему базовые параметры, которыми управляет логика. А от него унаследовать классы User и AI которые будут использовать эти параметры. И функция MoveUnit принимала бы базовый класс Unit и работала бы с ним абстрактно, не зная кто это.

UPD: поправил немного код, забыл class написать и в интерфейсе была ошибка

EvilOkta 21.02.2013 12:26

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от pax (Сообщение 253388)
Собственно вместо интерфейсов можно использовать наследование - унаследовать базовый класc Unit от MonoBehaviour, дать ему базовые параметры, которыми управляет логика. А от него унаследовать классы User и AI которые будут использовать эти параметры. И функция MoveUnit принимала бы базовый класс Unit и работала бы с ним абстрактно, не зная кто это.

Действительно не подумал, и такой и такой подход может помочь, пример с интерфейсами понятен более менее это как я понимаю альтернатива наследованию

pax 21.02.2013 12:31

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от EvilOkta (Сообщение 253390)
Действительно не подумал, и такой и такой подход может помочь, пример с интерфейсами понятен более менее это как я понимаю альтернатива наследованию

С# не поддерживает множественное наследование от классов (наследование линейное), зато можно наследоваться от множества интерфейсов.

EvilOkta 21.02.2013 12:47

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от pax (Сообщение 253391)
С# не поддерживает множественное наследование от классов (наследование линейное), зато можно наследоваться от множества интерфейсов.

т.е. один класс потомок может иметь только один класс-родитель? но можт иметь множественное число потомков, я правильно понимаю принцип наследования?

seaman 21.02.2013 13:37

Ответ: Передача переменной в метод
 
Как и в жизни - одна мать может родить кучу детей у которых будет ее наследственность. А учителя (интерфейсы) могут придать любому ребенку новые черты, не унаследованные от матери. Интерфейс может придать эти новые черты любому числу классов. Все они будут обладать неким общим набором свойств. И родители у этих классов могут быть разные.

EvilOkta 21.02.2013 14:07

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от seaman (Сообщение 253394)
Как и в жизни - одна мать может родить кучу детей у которых будет ее наследственность. А учителя (интерфейсы) могут придать любому ребенку новые черты, не унаследованные от матери. Интерфейс может придать эти новые черты любому числу классов. Все они будут обладать неким общим набором свойств. И родители у этих классов могут быть разные.

наглядно и полезно, спасибо большое.
А вот такой вопрос - при наследовании класса, его свойства наследует класс-потомок или конкретный экземпляр класса-потомка при создании?
Т.е. описывая класс-конструктор уже можно пользоваться свойствами базового класса?

pax 21.02.2013 14:34

Ответ: Передача переменной в метод
 
Не понял про класс конструктор, все экземпляры наследника имеют доступ к публичными и защищенным членам базового класса. Причем могут их переопределять, если они объявлены как виртуальные или абстрактные.

EvilOkta 21.02.2013 15:23

Ответ: Передача переменной в метод
 
да, порылся в справке, понял что задал глупый вопрос.
Попробую реализовать интерфейсами, мне кажется это будет более гибкая структура..
а get и set что определяет? сигнатуру метода переданного интерфейсу?

pax 21.02.2013 15:41

Ответ: Передача переменной в метод
 
Полезно будет почитать про свойства http://msdn.microsoft.com/ru-ru/library/x9fsa0sw.aspx

EvilOkta 21.02.2013 21:11

Ответ: Передача переменной в метод
 
Хотел узнать еще вот что (конечно понимаю что мои вопросы звучат совсем по ламерски но я видимо упускаю какие-то концепциии ООП, а точнее их реализации в Unity)
На старом примере немного непонятно взаимодействие классов и интерфейсов:
Если классы объявляются в разных скриптах, на разных GameObject (например на объекте игрока один скрипт, на враге другой) в одном соответственно объявляю класс User в другом AI, оба являются наследниками класса Unit - вот где этот базовый класс должен быть объявлен, чтобы оба класса наследника до него дотянулись? или без разницы?
Как в таком случае проектировать архитектуру программы - в какой момент инициализируется связи между классами? Я понимаю так, что при запуске программы должен запуститься какой-то базовый скрипт, в котором и будет объявлены все наследуемые классы и интерфейсы, но не могу понять как это происходит в отдельных независимых скриптах.
Или концепция ООП позволяет при запуске одного из скриптов получить все связи наследования из других.

Логику построения проекта на простом примере понимаю - взаимодействие скриптов происходит в момент наступление какого-то событие (пересечение с лучом, попадание в коллайдер и т. п.), а вот как быть с такими межскриптовыми связями наследования так и не понял, ведь каждый скрипт наследуется от monobehaviour а значит из за линейного наследования классы наследуются в пределах одного скрипта.

Тогда как определить общий интерфейс который действует из разных скриптов с общим методом одного из классов конкретного скрипта?

pax 21.02.2013 21:16

Ответ: Передача переменной в метод
 
1. Все скрипты проекта компилируются одновремено. Так что наследники получат все что имеет класс Unit в не зависимости в каком файле или папке проекта ты его создашь. Главное чтобы скрипты User и AI были в файлах с соответствующим именем (потому что их надо вешать на объекты как скрипты).

2. В функцию MoveUnit(Unit unit) можно будет передать и экземпляр AI и User т.к. они оба будут наследниками Unit.

seaman 21.02.2013 21:21

Ответ: Передача переменной в метод
 
Цитата:

в какой момент инициализируется связи между классами
В момент компиляции.
Цитата:

должен запуститься какой-то базовый скрипт, в котором и будет объявлены все наследуемые классы и интерфейсы
Ну компилятор (Моно) можно назвать таким "скриптом".
Цитата:

как быть с такими межскриптовыми связями наследования
Просто использовать. Все открытое в классе-родителе доступно в классе-потомке.
Цитата:

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

EvilOkta 21.02.2013 22:29

Ответ: Передача переменной в метод
 
Хм, пробую передать в метод переменную через интерфейс, компилятор ругается что я пытаюсь передать field как property, понимаю что несоответствие типов, тогда мне либо поле нужно объявить как свойство, либо научиться их передавать. Ниже скрипт (понимаю что много огорода). Задача передать интерфейсом поле UnitAngleNS и увеличить на 1. Для теста само собой.

PHP код:

using UnityEngine;
using System.Collections;

public interface 
IMoveDirection {
    
int Direction {getset;}
}

public class 
MoveGamer MonoBehaviourIMoveDirection {
    
    public 
bool UnitIsMove false// Движется ли юнит?
    
public float UnitCurrentAngle 100f// Скорость вращения юнита
    
public Vector3 UnitRotatingVectorUnitRotationPoint// Вектор вращения и точка вращения юнита
     
public    bool UnitSetMove true// Переменная отвечающая за инициализацию вектора
    
public int UnitAngleNSUnitAngleEW 0// Текущие углы поворота север-юг/запад-восток. Исходные углы = 0, Север+, Юг-, Восток-, Запад+
    
public string UnitDirection// Направление движения
    
public int UnitXPosUnitYPos;
    
    public 
int Direction
    
{
        
get{ return Direction;}
        
setDirection value;}
    }
    
    
// Use this for initialization
    
void Start () 
    {
    
    }
    
    
// Update is called once per frame
      
    
void Update () 
    {
         
UnitWaitMove (); // Юнит ожидает движение
    
}
    
    public 
void UnitWaitMove () 
    {    
    
        
// Блок выбора направления движения
        
if ((Input.GetKeyDown(KeyCode.W)) & !(UnitIsMove)) UnitDirection "North"// север
        
if ((Input.GetKeyDown(KeyCode.S)) & !(UnitIsMove)) UnitDirection "South"// юг
        
if ((Input.GetKeyDown(KeyCode.D)) & !(UnitIsMove)) UnitDirection "East"// восток
        
if ((Input.GetKeyDown(KeyCode.A)) & !(UnitIsMove)) UnitDirection "West"// запад
        
        
if (UnitDirection != ""UnitSetMove true// Если команда задана, то инициировать вектор поворота
        
if (UnitSetMoveRotatePlayerUnit(MoveGamer.UnitAngleNS);    
    }
    
        
    public 
void RotatePlayerUnit(Direction MoveGamer
    {
        
MoveGamer.Direction++;
        }
    }



pax 21.02.2013 22:37

Ответ: Передача переменной в метод
 
Direction в твоем случае свойство типа int (как поле), а не тип переменной который можно передавать в функицю. Правильно
вот так:
PHP код:

public void RotatePlayerUnit(IMoveDirection toMove)  
    { 
        
toMove.Direction++; 
    } 

PHP код:

RotatePlayerUnit(this); 


EvilOkta 21.02.2013 22:51

Ответ: Передача переменной в метод
 
Хм, а как быть с переменной UnitAngleNS которую я хотел передать или я интерфейс вообще не в ту степь повел? получается передаем свойство, но оно пустое и самодостаточное, как в него положить нужную мне переменную?

pax 21.02.2013 23:16

Ответ: Передача переменной в метод
 
Ты все еще привязываешь себя к переменным. Но теперь ты можешь передать объекты, обладающие одинаковыми свойствами в функцию обработки. Пусть функция меняет эти свойства объектов, а не непонятные переменные.

И на сколько я понял ты немного не так применил интерфейс.

PHP код:

public class User MonoBehaviourIMoveDirection 

    private 
int direction;
    public 
int Direction 
    

        
get{ return direction;} 
        
setdirection value;} 
    } 

PHP код:

public class AIMonoBehaviourIMoveDirection 

    private 
int direction;
    public 
int Direction 
    

        
get{ return direction;} 
        
setdirection value;} 
    } 

и тогда твоя функция будет вращать/двигать оба этих объекта используя интерфейс для свойства Direction.

вот так:
PHP код:

public void RotatePlayerUnit(IMoveDirection toMove)  

    
toMove.Direction++; 


PHP код:

RotatePlayerUnit(экземпляр_AI_или_User ); 

PS: private int direction; - это локальная переменная является хранилищем значения. Свойство само по себе это два метода, которые позволяют читать и записывать это значение и если надо делать какие-то дополнительные действия при чтении и сохранении.

EvilOkta 21.02.2013 23:53

Ответ: Передача переменной в метод
 
фух, разобрался с реализацией интерфейса при передаче в него одного свойства. Действительно зациклился на переменных, использование свойств более удобно (ура! +1 к опыту программирования).
Но теперь возник вопрос, а как быть если у объекта (this) есть два свойства и надо выборочно передать в метод лишь одно из них, ну или изменить одно из них?

Создал свойства DirectionNS и DirectionEW у объекта, изначально равны нулю. При передаче в метод RotatePlayerUnit надо увеличить либо одно из них, либо второе в зависимости от значения переменной UnitDirection. Есть способ?

PHP код:

using UnityEngine;
using System.Collections;

public interface 
IMoveDirection {
    
int Direction {getset;}
}

public class 
MoveGamer MonoBehaviourIMoveDirection {
    
    public 
bool UnitIsMove false// Движется ли юнит?
    
public float UnitCurrentAngle 100f// Скорость вращения юнита
    
public Vector3 UnitRotatingVectorUnitRotationPoint// Вектор вращения и точка вращения юнита
     
public    bool UnitSetMove true// Переменная отвечающая за инициализацию вектора
    
    
public string UnitDirection// Направление движения
    
public int UnitXPosUnitYPos;
    
    public 
int directionNS 0// Текущие углы поворота север-юг/запад-восток. Исходные углы = 0, Север+, Юг-, Восток-, Запад+
    
public int DirectionNS 
    

        
get{ return directionNS;} 
        
setdirectionNS value;} 
    }
    
    public 
int directionEW 0// Текущие углы поворота север-юг/запад-восток. Исходные углы = 0, Север+, Юг-, Восток-, Запад+
    
public int DirectionEW 
    

        
get{ return directionEW;} 
        
setdirectionEW value;} 
    }  
    
    
// Use this for initialization
    
void Start () 
    {
    
    }
    
    
// Update is called once per frame
      
    
void Update () 
    {
         
UnitWaitMove (); // Юнит ожидает движение
    
}
    
    public 
void UnitWaitMove () 
    {    
    
        
// Блок выбора направления движения
        
if ((Input.GetKeyDown(KeyCode.W)) & !(UnitIsMove)) UnitDirection "North"// север
        
if ((Input.GetKeyDown(KeyCode.S)) & !(UnitIsMove)) UnitDirection "South"// юг
        
if ((Input.GetKeyDown(KeyCode.D)) & !(UnitIsMove)) UnitDirection "East"// восток
        
if ((Input.GetKeyDown(KeyCode.A)) & !(UnitIsMove)) UnitDirection "West"// запад
        
        
if (UnitDirection != ""UnitSetMove true// Если команда задана, то инициировать вектор поворота
        
if ((UnitIsMove) & ((UnitDirection == "North") && (UnitDirection == "South"))) RotatePlayerUnit(this.directionNS);    
        if ((
UnitIsMove) & ((UnitDirection == "East") && (UnitDirection == "West"))) RotatePlayerUnit(this.directionEW);
    }
    
        
    public 
void RotatePlayerUnit(IMoveDirection toMove
    {
        
//float UnitAngle;
        //if (UnitSetMove) 
        //{
        //UnitRotationPoint = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z + 0.5f);
        //UnitRotatingVector = new Vector3(1,0,0);
        //UnitSetMove = !UnitSetMove;
        //}
            
        //transform.RotateAround(UnitRotationPoint, UnitRotatingVector, UnitCurrentAngle * Time.deltaTime);
        //UnitAngle = transform.eulerAngles.x;
            
        //if (UnitAngle == 90f) 
        //{
        //transform.rotation = Quaternion.Euler(90,transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z);
        //UnitIsMove = false;
        
toMove.Direction++;
        
//}
    
}



pax 22.02.2013 01:24

Ответ: Передача переменной в метод
 
Я вероятно все еще не понимаю что за система у тебя, что она просто меняет переменные не зная что она меняет и все счастливы) Ты все еще держишься за изменение переменных и интерфейс не применяешь как таковой.

По коду
PHP код:

// Блок выбора направления движения
        
if ((Input.GetKeyDown(KeyCode.W)) & !(UnitIsMove)) UnitDirection "North"// север
        
if ((Input.GetKeyDown(KeyCode.S)) & !(UnitIsMove)) UnitDirection "South"// юг
        
if ((Input.GetKeyDown(KeyCode.D)) & !(UnitIsMove)) UnitDirection "East"// восток
        
if ((Input.GetKeyDown(KeyCode.A)) & !(UnitIsMove)) UnitDirection "West"// запад 

Вот этот код выше присваивает переменной UnitDirection одно из значений North/South/East/West и следовательно ни одно из следующих условий не сработает, т.к. в условии обязательно в переменной наличие двух значений, что можно сделать только битовыми флагами, а не строками.
PHP код:

if ((UnitIsMove) & ((UnitDirection == "North") && (UnitDirection == "South"))) RotatePlayerUnit(this.directionNS);    
if ((
UnitIsMove) & ((UnitDirection == "East") && (UnitDirection == "West"))) RotatePlayerUnit(this.directionEW); 

Вот тут есть пример по перечислениям с битовыми флагами: http://msdn.microsoft.com/ru-ru/libr...attribute.aspx

И тут в коде нет того, что ты хочешь избежать - исключения конструкций if или case. Они есть и довольно сложные.

На мой взгляд твоя задача сводится к следующему:

PHP код:

public int RotatePlayerUnit(int toMove
{
        return 
toMove++;


PHP код:

this.directionEW RotatePlayerUnit(this.directionEW); 

Т.е. обычная функция, обрабатывающая значение и возвращающая результат, который присваивается той переменной, с которой было взято исходное значение. И эту функцию можно вызвать для всех переменных, требующих изменения хоть в цикле, хоть по условию.

EvilOkta 22.02.2013 10:49

Ответ: Передача переменной в метод
 
действительно, я все по ходу усложнил, положившись на понимание интерфейсов. Предложенное решение с передачей и обработкой функции - то, что надо.
Наверное еще не дорос я до оптимизации реализации кода, ну да ладно, буду стремиться.

Огромное спасибо за разъяснения, вынес из топика очень много нового!

EvilOkta 25.02.2013 11:21

Ответ: Передача переменной в метод
 
Еще один вопрос для понимания алгоритмов, как я понял при организации классов в Unity переменные следует использовать для расчетов, а свойства для хранения параметров игровх объектов.
А моей ошибкой было то, что я хранил значения параметров в переменных так? Т.е. если я переведу все необходимые параметры в свойства то смогу гораздо проще обрабатывать взаимодействия объектов?

и еще пара вопросов:
- что еще может содержать в себе свойство кроме значений? (или только значения?)
- может ли одно свойство содержать в себе несколько значений?

Понимаю что вопросов много, но они неизбежно возникают при изучении нового материала. Зато интересно! :)

pax 25.02.2013 11:33

Ответ: Передача переменной в метод
 
Цитата:

организации классов в Unity
Тут поправка на то, что организация классов не в Unity, а C#. Свойство - это поле с поддержкой выполнения операций при взятии значения и записывании (get и set). Полюс - свойство нельзя вывести в инспектор компонента как поле (это уже Unity).
Подробнее о свойствах http://msdn.microsoft.com/ru-ru/library/w86s7x04.aspx

И поле и свойство может содержать в себе экземпляр класса или структуры, который может иметь N полей. А еще они могут содержать ссылки на методы - делегаты.

EvilOkta 25.02.2013 12:05

Ответ: Передача переменной в метод
 
но чтобы вывести значение элемента свойства в инспектор в принципе можно в скрипте присвоить их значения какому-то полю, например хранилищу значения свойства? - ну для тестирования кода например

и еще разница в доступе к полям и свойствам конкретного объекта, хотел узнать так правильно? :
GameObject.Property++; //изменение свойства
GameField++; // изменение поля

А при доступе к объекту из других классов, как правильно делать подобное?

pax 25.02.2013 12:11

Ответ: Передача переменной в метод
 
По обращению свойство и поле не отличаются. Т.е. объект.свойство++ и объект.поле++ в коде записываются одинаково. Отличие в том, что в свойстве при этом сработает сначала метод get для взятия значения, а потом метод set для установки нового инкрементированного значения.

Я как-то писал маленькую статейку на тему обмена данными между скриптами

EvilOkta 25.02.2013 12:15

Ответ: Передача переменной в метод
 
полезная статья, спасибо!

EvilOkta 26.02.2013 23:03

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от pax (Сообщение 253737)
И поле и свойство может содержать в себе экземпляр класса или структуры, который может иметь N полей. А еще они могут содержать ссылки на методы - делегаты.

А можно пример синтаксиса объявления свойства, которое содержит в себе экземпляр класса? Пытаюсь найти в msdn но не нахожу.
И для чего можно использовать подобное,хотя бы простенький пример?

Заранее спасибо )

Цитата:

На мой взгляд твоя задача сводится к следующему:

PHP код:

public int RotatePlayerUnit(int toMove
{
        return 
toMove++;


PHP код:

this.directionEW RotatePlayerUnit(this.directionEW); 


Такой вопрос, конструкция заработала при использовании команды
PHP код:

return ++toMove

почему, ведь по идее увеличение значения должно происходить в обоих случаях? Или в первом случае сначала срабатывает return?

pax 27.02.2013 07:14

Ответ: Передача переменной в метод
 
PHP код:

public class VarsHolder{ public int var1; public string var2;}

public class 
MyClass{
     public 
VarsHolder myValues = new VarsHolder();

}

...

void Start()
{
   
myValues.var1++;


По поводу префиксной записи инкремента - префиксная запись сначала делает инкремент, потом возвращает это значение, постфиксная - как я написал теряет значение, потому что сначала возвращает старое значение, потом делает инкремент.

EvilOkta 03.03.2013 16:45

Ответ: Передача переменной в метод
 
Вопрос про перечисление.
Есть у меня перечисление следующего вида:
PHP код:

public enum Sector {SectorISectorIISectorIII

каким способом присваивать переменной конкретное значение перечисления я понял:
PHP код:

SomeParameter = (int)Sector.SectorI

А вот вопрос, как увеличить значение перечисления на 1? Независимо от текущего значения?
Я хочу достигнуть циклического параметра, т.е. при текущем значении пересечения SectorI он превращался в SectorII а из него в SectorIII и затем снова в SectorI. В справке не нашел способа как менять значение на следующее в списке перечисление (аналогично на предыдущее).

Пробую так:
PHP код:

if (Input.GetKeyDown(KeyCode.Space)) Sector = (Sector) (int) Sector++; 

но компилятор матерится, и до сих пор не понял как извлечь значение текущего пересечения и допустим присвоить его другой переменной?

Dream 03.03.2013 16:52

Ответ: Передача переменной в метод
 
это как самое простое и по хардкору
PHP код:

Sector var1=Sector.SectorI;
int value=(int)var1;
value+=1;
if(
value>(int)Sector.SecotrIII)
   
value=0;
var1=(Sector)value


EvilOkta 03.03.2013 17:05

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от Dream (Сообщение 254139)
это как самое простое и по хардкору
PHP код:

Sector var1=Sector.SectorI;
int value=(int)var1;
value+=1;
if(
value>(int)Sector.SecotrIII)
   
value=0;
var1=(Sector)value


спасибо, в принципе решение устраивает. Модернизировал вот так, чтобы не сбивался счетчик:
PHP код:

if (Input.GetKeyDown(KeyCode.Space)) {
            
Sec = (int)CurrentSectorNS;
            
Sec += 1;
            
CurrentSectorNS = (Sector)Sec;
            if (
Sec > (int)Sector.SectorIII) {
                
CurrentSectorNS Sector.SectorI;
                
Sec 0;
            }
        } 


EvilOkta 03.03.2013 17:22

Ответ: Передача переменной в метод
 
новая беда, где то туплю видимо.
выделил увеличение перечисления в отдельный метод, но он перестал из-за этого работать. Не могу понять что за фигня. Цель одним и тем же методом вертеть три перечисления:

PHP код:

using UnityEngine;
using System.Collections;

public class 
Unit MonoBehaviour {
        
    }



public class 
MoveGamer Unit {
    public 
enum Sector {SectorISectorIISectorIII// Ориентация секторов для определени углов поворота
    
public Sector CurrentSectorNSCurrentSectorWECurrentSectorAround// хранилища пересечений, Сектор текущего поворота по осям Север-Юг, Запад-Восток, Вокруг себя
    
public int Sec// отладка
    
    // Use this for initialization
    
void Start () 
    {
    
CurrentSectorNS CurrentSectorWE CurrentSectorAround Sector.SectorI;    
    }
    
    
// Update is called once per frame
      
    
void Update () 
    {
         
UnitWaitMove (); // Юнит ожидает движение
    
}
    
    public 
void UnitWaitMove () 
    {    
    
        if (
Input.GetKeyDown(KeyCode.X)) ChangeSector (CurrentSectorNS);
        if (
Input.GetKeyDown(KeyCode.C)) ChangeSector (CurrentSectorWE);
        if (
Input.GetKeyDown(KeyCode.V)) ChangeSector (CurrentSectorAround);
    }
        
    public 
Sector ChangeSector(Sector ChangeSector) {
        
Sec = (int)ChangeSector;
        
Sec += 1;
        
ChangeSector = (Sector)Sec;
        if (
Sec > (int)Sector.SectorIII) {
            
ChangeSector Sector.SectorI;
            
Sec 0;}
        return 
ChangeSector;
    }



EvilOkta 03.03.2013 17:27

Ответ: Передача переменной в метод
 
вопрос снят, был дураком, разобрался сам. Неправильно выполнял метод
PHP код:

if (Input.GetKeyDown(KeyCode.X)) CurrentSectorNS ChangeSector(CurrentSectorNS);
if (
Input.GetKeyDown(KeyCode.C)) CurrentSectorWE ChangeSector(CurrentSectorWE);
if (
Input.GetKeyDown(KeyCode.V)) CurrentSectorAround ChangeSector(CurrentSectorAround); 


EvilOkta 03.03.2013 21:55

Ответ: Передача переменной в метод
 
Хм, опять застрял в тупике. Объявляю массив:
PHP код:

public int[,] AngleArray = new int[3,2];
    
void Start () 
    {
    
AngleArray[0,0]    = 270AngleArray[0,1]    = 0AngleArray[0,2] = 90;
    
AngleArray[1,0]    = 180AngleArray[1,1]    = 270AngleArray[1,2] = 0;
    
AngleArray[2,0]    = 90AngleArray[2,1]    = 180AngleArray[2,2] = 270;
    
AngleArray[3,0]    = 0AngleArray[3,1]    = 90AngleArray[3,2] = 180;


компилятор радостно машет index out of range
почему?

Dream 03.03.2013 23:51

Ответ: Передача переменной в метод
 
Максимум для твоего масива - [2,1].
Я думаю тебе стоит почитать про основы языка, чтобы не спрашивать каждый час на форуме о банальной проблеме

EvilOkta 03.03.2013 23:59

Ответ: Передача переменной в метод
 
читаю основы, но сказывается то, что раньше изучал blitz 3d, сложно сразу отвязаться от него
непонятно почему максимум [2,1] - в С# по другому задаются пределы массива?
в mdsn написано что "Индексация массивов начинается с нуля: массив с элементами n индексируется от 0 до n-1."
у меня размерность массива 4 элемента на 3 или при индексации с 0 - 3х2.

или я не так понял синтаксис?

upd: все разобрался, оказывается при объявлении массива нумерация начинается с 1, а при доступе к элементам с 0.
Не такой очевидный ньюанс, ибо в blitz объявление тоже было с 0.

Dream 04.03.2013 00:30

Ответ: Передача переменной в метод
 
При обьявлении ты указываешь размер, и от нуля до 2 какраз поучается те твои 3 элемента. протсо нужно привыкнуть. Всётаки читай msdn. Меньше вопросов будет.

EvilOkta 04.03.2013 22:13

Ответ: Передача переменной в метод
 
и снова нубский вопрос (да-да, только что из справки и тестирования скрипта)
Я научился поворачивать объект с помощью rotatearound и с помощью quaternion.slerp
а теперь вопрос - как объединить эти два способа в один? Мне нужно вращать объект вокруг определенной точки в пространстве используя кватернионы (ибо с помощью углов эйлера получаю шарнирный замок в одном из положений)
вращать вокруг центра объекта - понятно как, а вот как это сделать с помощью transform.RotateAround неясно, ибо оно хочет в качестве параметров два вектора а не кватернионы.

рассматриваю вариант вращения через дочерние пивоты но мне этот метод кажется черезчур проблемным, ибо количество таких пивотов и их настройка слишком суровая заявка для простого поворота объекта на заданный угол вокруг определенной точки.

Вот если бы как то в transform.RotateAround передать кватернион либо решить проблему шарнирного замка (читал про обход проблемы через вращение матрицами, но если честно нихрена не понял).

Надеюсь хотя бы пнете в нужном направлении. ))

p.s. тему впору переименовать в нубские вопросы очередного новичка ))

pax 04.03.2013 22:55

Ответ: Передача переменной в метод
 
Самое простое - поместить пустой объект в точку поворота, поместить твой объект в чайлды к пустому, повернуть пустышку как надо, вывести твой объект из чайлдов пустышки, убить пустышку.

Пустышку можно и не убивать, так будет быстрее.

EvilOkta 04.03.2013 23:01

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от pax (Сообщение 254195)
Самое простое - поместить пустой объект в точку поворота, поместить твой объект в чайлды к пустому, повернуть пустышку как надо, вывести твой объект из чайлдов пустышки, убить пустышку.

Пустышку можно и не убивать, так будет быстрее.

хорошая идея, спасибо! Нужно будет немного поменять скрипт но должно сработать. В принципе position для этой пустышки можно будет взять из positiona вектора для rotatearound.
А с привязкой/отвязкой дочерних объектов буду штудировать справку.

pax 04.03.2013 23:33

Ответ: Передача переменной в метод
 
transform.parent = pivot.transform сделает объект дочерним к объекту pivot
transform.parent = null - сделает объект самостоятельным

EvilOkta 18.03.2013 00:04

Ответ: Передача переменной в метод
 
Третий час бьюсь над косяком в скрипте, кто поможет?
В общем задача скрипта практически завершена, но периодически появляются глюки.
Скрипт по команде кнопок WSAD (это пока-что) перекатывает юнит на соседнее поле. RotationPivot - объект который используется как точка через которую идет перекатывание.

Скрипт работает как часы, но в некоторых позициях (например при последовательности W-A-W) юнит начинает перекатываться через другую ось (а именно ось Y, хотя скрипт однозначно вращает только по X и Z) - как можно вылечить?

PHP код:

using UnityEngine;
using System.Collections;

public class 
Unit MonoBehaviour {
    private 
string UnitName// Наименование юнита
    
public int unitNSPositionunitWEPosition//Позиция юнита в координатах
    
public Transform RotationPivot// Точка вращения юнита
    
public Quaternion RotateFromRotateTo// Кватернионы вращения (начало-конец)
    
}

public class 
MoveGamer Unit {
    
    public    
bool UnitSetMove// Переменная отвечающая за инициализацию вектора
    
public bool UnitIsMove// Движется ли юнит?
    
public float UnitCurrentAngle// Скорость вращения юнита
    
public float CurrentUnitAngleNSCurrentUnitAngleAroundCurrentUnitAngleWE// Текущий уровень поворота юнита
    
public string UnitDirection// Направление движения
    
public enum Sector {SectorISectorIISectorIIISectorIV// Ориентация секторов для определени углов поворота
    
public Sector CurrentSectorNSCurrentSectorWECurrentSectorAround// Сектор текущего поворота по осям Север-Юг, Запад-Восток, Вокруг себя
    
    
    
void Start ()     {
        
UnitCurrentAngle 0;    
        
UnitIsMove false;
        
UnitSetMove false;    
        
CurrentSectorNS CurrentSectorWE CurrentSectorAround Sector.SectorI;    
    }
    
    
void Update ()     {
         
UnitWaitMove (); // Юнит ожидает движение
    
}
    
    public 
void UnitWaitMove () {    
        
// Блок выбора направления движения (времянка)
        
if ((Input.GetKeyDown(KeyCode.W)) & !(UnitSetMove)) UnitDirection "North"// север
        
if ((Input.GetKeyDown(KeyCode.S)) & !(UnitSetMove)) UnitDirection "South"// юг
        
if ((Input.GetKeyDown(KeyCode.D)) & !(UnitSetMove)) UnitDirection "East"// восток
        
if ((Input.GetKeyDown(KeyCode.A)) & !(UnitSetMove)) UnitDirection "West"// запад
        
        
if ((UnitDirection != "") & !UnitIsMoveSetPointToRotation (); // Если команда задана, то инициировать точку поворота
        
if (UnitIsMoveRotatePlayerUnit (); // Если юнит в движении то выполнить поворот    
    
}
        
    public 
void RotatePlayerUnit()     {
        
RotationPivot.transform.rotation Quaternion.Lerp(RotateFrom,RotateToUnitCurrentAngle);    // Повернуть юнит
        
UnitCurrentAngle += 0.1f// изменение угла
        
if (UnitCurrentAngle 1fStopMove (); // Если поворот завершен, то остановить движение
    
}
    
    
// метод меняющий значение сектора поворота
    
public Sector ChangeSector(Sector ChangeSectorint Direct) {
        
int Sec = (int)ChangeSector// переменная показывающая текущий сектор
        
Sec += Direct// увеличение/уменьшение сектора в зависимости от входного параметра
        
Sec = (Sec > (int)Sector.SectorIV) ?  Sec;
        
Sec = (Sec < (int)Sector.SectorI) ?  Sec//условия перехода сектора через 0
        
ChangeSector = (Sector)Sec// установка сектора
        
return ChangeSector// возврат метода
    
}
    
    public 
void SetPointToRotation ()    {
        
// задаем смещение позиции родительского элемента относительно юнита, для вращения
        
float SetXSetZ//переменные позиции родителя
        
SetX SetZ 0f;
        
        
RotateFrom transform.rotation// Снять "слепок" текущего значения поворота
        
        
switch (UnitDirection) { // установка точки поворота
            
case "North"
                
SetX 0.5fSetZ 0f// позиция точки относительно юнита
                
CurrentUnitAngleWE -= 90f// приращение угла
                
CurrentUnitAngleWE = (CurrentUnitAngleWE 0) ? 270 CurrentUnitAngleWE// проход угла через 0
                
break;
            case 
"South"
                
SetX = -0.5fSetZ 0f;
                
CurrentUnitAngleWE += 90f;
                
CurrentUnitAngleWE = (CurrentUnitAngleWE 360) ? 90 CurrentUnitAngleWE;
                break;    
            case 
"West"
                
SetX 0fSetZ 0.5f;
                
CurrentUnitAngleNS += 90f;
                
CurrentUnitAngleNS = (CurrentUnitAngleNS 360) ? 90 CurrentUnitAngleNS;
                break;    
            case 
"East"
                
SetX 0fSetZ = -0.5f;
                
CurrentUnitAngleNS -= 90f;
                
CurrentUnitAngleNS = (CurrentUnitAngleNS 0) ? 270 CurrentUnitAngleNS;
                break;        
        }
        
        
RotateTo Quaternion.Euler(CurrentUnitAngleNSCurrentUnitAngleAroundCurrentUnitAngleWE); // установка кватерниона поворота
        
RotationPivot.position = new Vector3(transform.position.SetXtransform.position.0.5ftransform.position.SetZ); // устанавливаем точку вращения
        
this.transform.parent RotationPivot.transform// привязываем юнит к родителю
        
UnitIsMove true// начнаем вращение
        
UnitSetMove false// заканчиваем инициализацию
    
}
    
    public 
void StopMove ()    {
        switch (
UnitDirection) {
            case 
"North"
                
CurrentSectorNS ChangeSector (CurrentSectorNS, -1); // изменение сектора вращения
                
unitNSPosition += 1// изменить позицию
                
break;
            case 
"South"
                
CurrentSectorNS ChangeSector (CurrentSectorNS1);
                
unitNSPosition -= 1;
                break;    
            case 
"West"
                
CurrentSectorWE ChangeSector (CurrentSectorWE1);
                
unitWEPosition += 1;
                break;    
            case 
"East"
            
CurrentSectorWE ChangeSector (CurrentSectorWE, -1);
            
unitWEPosition -= ;
            break;        
    }
    
// блок завершения движения
        
RotationPivot.rotation RotateTo// выровнять угол поворота (доводчик)
        
UnitCurrentAngle 0f;    // обнулить угол
        
transform.parent null// овязать точку вращения
        
UnitIsMove false// закончить движение
        
UnitDirection "";    // обнулить команду на движение
    
}



seaman 18.03.2013 00:10

Ответ: Передача переменной в метод
 
Скорее всего это из-за использования углов Эйлера для поворота.
Использование углов Эйлера может завести в тупик

EvilOkta 18.03.2013 00:17

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от seaman (Сообщение 255104)
Скорее всего это из-за использования углов Эйлера для поворота.
Использование углов Эйлера может завести в тупик

я же преобразую углы эйлера в кватернион и вроде не вращаю именно углами. Или даже кватернион задавать углами эйлера нельзя?

запутался, как раз переделал скрипт чтобы в такую ловушку не попасться, и все равно :-D

pax 18.03.2013 00:38

Ответ: Передача переменной в метод
 
Вращай последовательно. По введенным направлениям. А не сразу на весь поворот.

EvilOkta 18.03.2013 15:06

Ответ: Передача переменной в метод
 
Цитата:

Сообщение от pax (Сообщение 255109)
Вращай последовательно. По введенным направлениям. А не сразу на весь поворот.

идея понятна, но как тогда проверять дошел ли юнит до определенного угла? эйлерами?


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

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