1. if (owner == none) if (owner = none) или if (Weapon = none) if (Weapon == none)
Есть ли разница между = и == для движка или можно писать так и так? Я перевел все это так : если нет пешки (владельца), если нет оружия...
2. По поводу команды continue If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать Судя по этой команде " ничего не делать" Бот, когда видит игрока, должен перестать стрелять в игрока, доджиться и т. д. но бот все это делает, как же так? Что именно запрещает делать continue ?
Сообщение отредактировал Gadavre - Пятница, 16 Декабрь 16, 20:43
Я перевел все это так : если нет пешки (владельца), если нет оружия...
Правильно перевели.
if (owner = none) или if (Weapon = none) просто не скомпилируется. Условие If(*** == ***) требует ОБЯЗАТЕЛЬНО двойного знака равно.
== это сравнение = это присвоение.
Оператор weapon = nonе; присваивает оружию значение none. То есть игра будет считать, что в руках у бота нет никакого оружия. (Независимо от того, есть оно у него в руках или нет).
Команда continue в программировании означает завершение обработки данного актера и переход к следующему.
Конкретно в моем коде:
ForEach AllActors(class'Bot', B) { if (B.Health <= 0 || B.weapon == None) continue; // Не обрабатывать мертвых и безоружных ботов If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать
Оператор ForEach AllActors(class'Bot', B)перебирает всех ботов по очереди. То есть если на уровне, допустим, три бота. он "смотрит" сначала первого бота, затем второго, затем третьего. команда If (B.LineOfSightTo(P)) continue; означает, что если бот видит игрока, скрипт перестает интересоваться действиями данного бота, и переходит к следующему. Соответственно, данный бот не получает никаких приказов, и продолжает выполнять те, что были отданы ранее. Поскольку бот стреляет в "медальку" только по прямому приказу, выстрелить в "медальку" он не сможет. Однако, если бот видит игрока, он может стрелять в него, как это было бы в обычной игре.
Результатом действия данной команды является то, что если бот видит игрока, он ВСЕГДА действует так, как это ему положено в обычной игре. В "медальку" он стреляет лишь в случае, если НЕ ВИДИТ ИГРОКА.
Команды Return, Сontinue и Break - близницы братья.
Return означает аварийный выход из функции с прекращением всех дальнейших действий по её выполнению. Break означает аварийный выход из цикла с прекращением всех дальнейших действий по его выполнению и переходом к первой следующей ПОСЛЕ ЦИКЛА команде. Сontinue означает аварийный выход из цикла с переходом к следующему элементу цикла. То есть если цикл обрабатывал Бота №2, то по командеСontinue он переходит к Боту №3 (если таковый имеется)
Сообщение отредактировал Reborn - Пятница, 16 Декабрь 16, 20:42
Добавлено (16 Декабря 16, 20:37) ---------------------------------------------
ЦитатаGadavre ()
Да, можете поиграться с высотой мишени, а так же её коллизией.(там по умолчанию 22 высота 22 радиус) Можно изменить высоту и радиус в defaultproperties, как это сделано в других скриптах.
Кроме этого, можете добавить строку If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать If (!B.LineOfSightTo(Self)) continue; // Если бот не видит мишень - ничего не делать If (!P.LineOfSightTo( B ) ) continue; // Если ИГРОК НЕ МОЖЕТ ВИДЕТЬ БОТА - ничего не делать
Добавил эту последнюю строку и бот стал уязвим - перестал стрелять сразу, когда появлялся в небольшом поле зрения игрока. Нет, это условие ослабляет бота.
Код
if (owner != none && P != Owner) Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64))); // В этом случае для другого игрока спаунится другая мишень.
// перемещаем мишень вместе с хозяином if (P == Owner) { if(P.bIsCrouching) SetLocation (P.Location + Vect(0,0,15)); // Ниже, если на корточках. else SetLocation (P.Location + Vect(0,0,30)); //На высоте головы
Даже при таких низких значениях высоты медальки бот все таки умудряется иногда убить игрока, когда тот его не видит. Отличие от ваших значений только в том, что бот убивает реже , иногда просто пробегает без выстрела позицию атаки. Не знаю что делать. Опустить что ли медаль еще ниже в пятки игрока? Такое чувство, что при определенном условии горизонтальная платформа на которой стоит игрок для бота ИНОГДА не является припятствием и пуля просто просто проходит через нее в медаль...
Код
if (owner != none && P != Owner) Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64)));
Эту строку я не изменял, но тем не менее и она вызывает вопросы. Почему 64, когда в аналогичнойстроке ниже у вас было значение 50, которое я понизил до 30? Ведь медаль будет спавниться как мне кажется у разных игроков на разных высотах!
Сообщение отредактировал Gadavre - Пятница, 16 Декабрь 16, 20:58
Даже при таких низких значениях высоты медальки бот все таки умудряется иногда убить игрока, когда тот его не видит. Отличие от ваших значений только в том, что бот убивает реже , иногда просто пробегает без выстрела позицию атаки.Не знаю что делать. Опустить что ли медаль еще ниже в пятки игрока? Такое чувство, что при определенном условии платформа на которой стоит игрок для бота ИНОГДА не является припятствием и пуля просто просто проходит через нее в медаль...
В "прохождении через прияпятствия" пули не замечены. Проблема в другом: цилиндр коллизии значительно шире головы игрока. и сильно за неё выступает. Стреляя в направлении игрока, бот "случайно" в него попадает.
Я нарисовал вам картинку, чтобы вы понимали, что происходит.
Опыт показывает, что нет неразрешимых проблем, но есть проблемы, над которыми надо думать.
А попробуйте вместо
If (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока B.FaceTarget = Self; // Смотреть в лицо игроку B.target = Self; // Цель = мишень = лицо игрока. B.bShootSpecial = true; // Эта опция разрешает стрелять не в игрока а в мишень. if (P.LineOfSightTo(B )&& !NeedToTurn(B )B.FireWeapon(); // Если бот повёрнут лицом к игроку - стрелять else B.gotostate('RangedAttack','FaceTarget' ); // В противном случае повернуться лицом к игроку
Написать
If (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока B.FaceTarget = Self; B.gotostate('RangedAttack','FaceTarget');
И отпишитесь о результатах.
В этом случае бот не сбудет стрелять в медальку вообще, а будет стрелять только в самого игрока. У меня бот при этом попадает значительно реже, но при этом делает значительно меньше "лишних" выстрелов. Может так лучше будет?
if (owner != none && P != Owner) Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64)));Эту строку я не изменял, но тем не менее и она вызывает вопросы. Почему 64, когда в аналогичнойстроке ниже у вас было значение 50, которое я понизил до 30? Ведь медаль будет спавниться как мне кажется у разных игроков на разных высотах!
Положение медальки обновляется каждую секунду. Какая, к черту, разница, где её спавнить, если через секунду она переместится туда, куда вы укажите. Можете вообще отспауить её под землей. if (owner != none && P != Owner) Spawn(class'ShootTarget',P,,(vect(0,0,-10000)));
ЦитатаGadavre ()
Даже при таких низких значениях высоты медальки бот все таки умудряется иногда убить игрока, когда тот его не видит.
У вас же как-то считается дамаж от вашей винтовки? Грубое решение: напишите, что если убитый не может видеть своего убийцу, попадание в голову не засчитывается. В классе оружия:
function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z) { local UT_Shellcase s;
Подробно разобрал последнюю функцию попадания пули в цель, чтобы вы понимали, что происходит. По идее, построчно нужно разбирать весь код, который вы используете.
// Эта функция вызывается при попадании пули. function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z) { // UT_Shellcase - это гильза. local UT_Shellcase s;
// Сначала создается гильза рядом с винтовкой. Эта строка отвечает за её положение. s = Spawn(class'UT_ShellCase',, '', Owner.Location + CalcDrawOffset() + 30 * X + (2.8 * FireOffset.Y+5.0) * Y - Z * 1);
// Если гильзу удалось создать, if ( s != None ) { // Её размер равен 2 (потому что гильза от снайперской пули вдвое больше гильзы от автомата) s.DrawScale = 2.0;
// После чего она отбрасывается в сторону (эта строка отвечает за силу её отброса) s.Eject(((FRand()*0.3+0.4)*X + (FRand()*0.2+0.2)*Y + (FRand()*0.3+1.0) * Z)*160); }
// Если жертвой является сам уровень - то есть при попадании в стену. if (Other == Level) Spawn(class'UT_HeavyWallHitEffect',,, HitLocation+HitNormal, Rotator(HitNormal)); // Спаунится класс UT_HeavyWallHitEffect - то есть пятно на стене.
// Если жертвой не является сама снайперская винтовка, или её хозяин, или никто вообще. else if ( (Other != self) && (Other != Owner) && (Other != None) ) {
// Новая строка: Если жертвой является игрок, стрелком бот, и попадание в голову, и игрок не может видеть бота - дальнейшаяобработкафункции прекращается. if (PlayerPawn(Other) != None && Bot(Owner)!= None && (HitLocation.Z - Other.Location.Z > 0.62 * Other.CollisionHeight)&& !PlayerPawn(Other).LineOfSightTo(Owner)) return;
// Если жертвой является Pawn - то есть игрок, бот, монстр, или неигровой персонаж, например, рыбка или муха if ( Other.bIsPawn ) Other.PlaySound(Sound 'ChunkHit',, 4.0,,100); // раздается звук попадания в тело
/* Если: 1) жертвой является Pawn, 2) попадание выше, чем 62% коллизии (то есть в верхние 38% коллизии) 3) стрелком является игрок 4) ИЛИ стрелком является бот, но не Novice, то есть не "новичок", а высокоуровневый бот. */ if ( Other.bIsPawn && (HitLocation.Z - Other.Location.Z > 0.62 * Other.CollisionHeight) && (instigator.IsA('PlayerPawn' ) || (instigator.IsA('Bot' )&& !Bot(Instigator).bNovice)) ) Other.TakeDamage(100, Pawn(Owner), HitLocation, 35000 * X, AltDamageType); /* Ему наносится урон 100 единиц здоровья, класс урона AltDamageType. 1) класс AltDamageType заявлен как обезглавливание. 2) урон 100 единиц здоровья заявлен для стиля игры Classic. В стиле Хардкор и Турбо урон увеличивается в полтора раза, и будет 150 единиц. */
else Other.TakeDamage(45, Pawn(Owner), HitLocation, 30000.0*X, MyDamageType); /* В противном случае (то есть в случае, если: 1) Жертвой не является живое существо (Pawn), а, например стена или бочка. 2) или попадание в нижние 62% коллизии Pawn-а 3) или стрелком является Novice - "низкоуровневый" бот) Жертве наносится урон 45 единиц здоровья, класс урона MyDamageType. При этом: 1) класс MyDamageType заявлен как попадание пули. 2) урон 45 единиц здоровья заявлен для стиля игры Classic. В стиле Хардкор и Турбо урон увеличивается в полтора раза, и будет 67 единиц.*/
// Ну и последнее: если жертва не живое существо(Pawn) и не труп (Carcass) if ( !Other.bIsPawn && !Other.IsA('Carcass' ) ) spawn(class'UT_SpriteSmokePuff',,,HitLocation+HitNormal*9); // в точке попадания пули спаунится дымок (класс UT_SpriteSmokePuff) - например при попадании в стену или в бочку.* } }
Добавлено (17 Декабря 16, 07:29) --------------------------------------------- Этот код находится в классе снайперской винтовки, если будете его менять - просто перенесите в свой класс.
Добавлено (17 Декабря 16, 07:33) --------------------------------------------- Обработка случаев, когда нет гильзы или нет жертвы нужна для того, чтобы движок не пытался управлять несуществующим актером. Гильза, например, не создается. если игрок стоит вплотную к стене.
Сообщение отредактировал Reborn - Суббота, 17 Декабрь 16, 07:58
1. дописал в function ProcessTraceHit вашу строку if (PlayerPawn(Other) != None && Bot(Owner)!= None && (HitLocation.Z - Other.Location.Z > 0.62 * Other.CollisionHeight)&& !PlayerPawn(Other).LineOfSightTo(Owner)) return;
В классе ShootTarget ничего не менял. Хотя игрок не видит в этой позиции бота (файл прикреплен), выбегающего из лифта к прямоугольному проему внизу,бот все равно продолжает стрелять в игрока. Если LineOfSight линия соединяющая центры коллизии бота и игрока, то можно предположить что эта линия прерывается платформой на которой игрок стоит и этот код по этой причине может не работать.
2.
ЦитатаReborn ()
А попробуйте вместоIf (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока B.FaceTarget = Self; // Смотреть в лицо игроку B.target = Self; // Цель = мишень = лицо игрока. B.bShootSpecial = true; // Эта опция разрешает стрелять не в игрока а в мишень. if (P.LineOfSightTo(B ) && !NeedToTurn(B ) B.FireWeapon(); // Если бот повёрнут лицом к игроку - стрелять else B.gotostate('RangedAttack','FaceTarget' ); // В противном случае повернуться лицом к игроку
Написать
If (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока B.FaceTarget = Self; B.gotostate( 'RangedAttack','FaceTarget' ) ;
И отпишитесь о результатах.
Отписываюсь. Бот продожает выстреливать патроны в игрока, который его не видит, но его пули уже не задевают игрока. В изначальном коде как я помню задевали. Если подойти чуть к краю платформы, чтобы бот видел только голову, то godlike бот, стреляя, начинает мазать, иногда попадает.
3. Если не найду другого решения то останавлюсь на понижении высоты медали. Пока остановился на:
При таком значении бот уже не стреляет, если вне видимости, бегал он у меня на компе полчаса и не выстрелил. Если двинуться чуть вперед, чтобы была узкая щель обзора, то бот начинает стрелять, но не всякий раз когда показывается на глаза. Думаю это реалистично и живой игрок не сразу же бы заметил без оптики на месте бота голову или полголовы игрока со снайперкой на таком большом расстоянии. Я так понимаю, бот реагирует не только на медальку, но и на ее коллизию, которая при вашем значении SetLocation (P.Location + Vect(0,0,50)) наверняка выходила за пределы головы игрока в высоту, оттого бот и убивал игрока в тех случаях, когда игрок его не видел. Это возможно?
4. К сожалению медаль видимой сделать не получилось, хотя поменял значение до 128, прописал bHidden=False, двигался и одновременно смотрел вверх. Знаю только, что она выглядит согласно едитору в форме сундучка. Но я и не расстраиваюсь. --------------------------------------------------------------------------------------------------------------------------------------------- Спасибо за помощь! Такой сложный код в классе ShootTarget написать под силу только профи, кем вы и являетесь. Я обязательно сохраню ваши учебные посты себе на комп, не удаляйте их пожалуйста. ---------------------------------------------------------------------------------------------------------------------------------------------
Добавлено (18 Декабря 16, 19:38) --------------------------------------------- как можно записать суицид игрока в промежутке между 100 поинтов здоровья, и 30 ? Я записал так в function timer (), но не работает, не знаю какой вообще синтаксис нужен.
Код
function Timer() { local Pawn P;
for ( P=Level.PawnList; P!=None; P=P.NextPawn ) { if (P.IsA( 'PlayerPawn' )) { if (P.health < 100 || P.health > 30) { P.died(None, '', Location); } }
1) Таймер не работает сам по себе. Его надо вызывать. function PostBeginPlay() { Super.PostBeginPlay(); SetTimer (1.0, true); }
Здесь 1.0 промежуток времени, а True - повторение таймера. (если написать false таймер сработает 1 раз и остановится)
2) Ваш код написан так. что Павн умрет в любом случае: Здоровье меньше 100 или больше 30. Очевидно нужно писать не "или" || а "и" &&
function Timer() { localPawn P;
for ( P=Level.PawnList; P!=None; P=P.NextPawn ) if (P.IsA('PlayerPawn') &&P.health > 30&&P.health < 100) P.Died(None, 'Suicided', Location); }
Когда используете какую-то функцию, смотрите, как это сделано в других скриптах. Для самоубийств есть специальный класс урона - 'Suicided'.
Добавлено (19 Декабря 16, 21:03) --------------------------------------------- //========================================== Добавлено: По поводу функции PostBeginPlay() Функция PostBeginPlay() вызывается к любому актеру после загруузки уровня. По этому на неё удобно вешать события, который обязательно должны случиться. Строка Super.PostBeginPlay(); необходима для того, чтобы не было глюков. (Она сообщает движку о том, что все приказы, записанные в эту функцию в родительских классах так же остаются действительными).
Сообщение отредактировал Reborn - Понедельник, 19 Декабрь 16, 20:47
function ModifyPlayer(Pawn Other) { // called by GameInfo.RestartPlayer() if ( NextMutator != None ) NextMutator.ModifyPlayer(Other); }
function ScoreKill(Pawn Killer, Pawn Other) { // called by GameInfo.ScoreKill() if ( NextMutator != None ) NextMutator.ScoreKill(Killer, Other); }
Я заметил, что в некоторых мутаторах кодеры в каждой функции вместо стандартных строк начинающихся со if ( NextMutator != None )... пишут строки со словом Super. Super. ModifyPlayer(Other) Super.ScoreKill(Killer, Other) и т. д. Мне также лучше так писать? Если да, то чем лучше? По моему строка с if ( NextMutator != None )... улучшает совместимость мутатора с другими мутаторами.... А как на самом деле?
Нашел в классе PlayerPawn игры вот такой странный код. Почему в условии написано, что если здоровье больше нуля, то будет суицид? Наоборот должно быть меньше! Я прыгал вниз с большой высоты и у меня оставалось минимут 24 пойнта и игрок был жив...
Super-Puper блин. Вы серьезно игнорируете советы подтянуть теорию и осилить туториалы. Super это отсылка к родительскому класу, к тому что прописано после extends. Любая функцыя, например эта в мутаторе
Код
function ScoreKill(Pawn Killer, Pawn Other) { // called by GameInfo.ScoreKill() if ( NextMutator != None ) NextMutator.ScoreKill(Killer, Other); }
по сути переопределение. Тоесть если где-то выше в класе (Mutator или еще выше) что-то исполнялось в этой фукцыи, то оно больше исполнятса не будет, ибо в вашем коде его нет. Для этого и используетса Super, это как Master или Father чтоли. Например сдесь
Код
if ( NextMutator != None ) NextMutator.ScoreKill(Killer, Other);
передаетса событие следующему мутатору, кода тут мало. А если много, то вместо того чтоб переписывать все можно в своем мутаторе одной строчкой так
Код
function ScoreKill(Pawn Killer, Pawn Other) { // свой код до основонго Super.ScoreKill(Killer, Other); // если эту строчку убрать, то событие следующему мутатору не передастса // или после основонго }
GP Здраствуйте GP! Очень рад, что вы подключились к беседе.
То есть, простым понятным языком, если я в function ScoreKill напишу свой код и в этой функции будет эта строка
Код
Super.ScoreKill(Killer, Other);
То , если я подключу к своему мутатору другой мутатор, то код будет работать в игре с обоими мутаторами. В обратном случае код мутатора не будет работать в связке с другим мутатором. Верно?
Сообщение отредактировал Gadavre - Понедельник, 19 Декабрь 16, 23:28
UnrealScript имеет древовидную структуру, в котором каждый объект наследует все свойства, переменные и функции родительского класса.
К примеру, если вы создаете подкласс оружия extends SniperRifle, то выглядить она будет как обычная SniperRifle, хотя в скрипте это явно не указано. Новое оружие "унаследовало" все свойства старого.
Так же и с функциями: все функции, которые есть в "старшем" классе будут по-прежнему выполняться, хотя в скрипте они не прописаны.
Но, допустим, вы создаете функцию с именем, которое уже есть в старшем классе. (Та же PostBeginPlay(), например).
Будет она выполняться или нет?
Написав код: function PostBeginPlay() { SetTimer (1.0, true); }
Вы ПЕРЕЗАПИСЫВАЕТЕ эту функцию, и всё, что было в ней в старшмх классах (Object -> Actor -> Inventory -> Weapon -> TournamentWeapon -> SniperRifle) выполняться не будет. Это может привести к глюкам, если там было прописано что-то критически важное для игры.
Поэтому, используя функцию, которая уже есть в старших классах, пишут: function PostBeginPlay() { Super.PostBeginPlay(); SetTimer (1.0, true); }
Где строка Super.PostBeginPlay();означает приказ выполнить ту же фцнкцию в старшем классе.
ИНЫМИ СЛОВАМИ, КОМАНДА SUPER.ИМЯ_ФУНКЦИИ() ОЗНАЧАЕТ ПРИКАЗ ВЫПОЛНИТЬ ФУНКЦИЮ НЕ В ДАННОМ КЛАССЕ, А В РОДИТЕЛЬСКОМ.
В случае с Super.PostBeginPlay();вы можете выбрать, в какой момент будет выполнена функция родительском классе - до или после вашего кода.
Функция PostBeginPlay() является одной из базовых в классе Actor, и вызывается для всех Актеров. Мне было лениво смотреть всю цепочку вызовов в старших классах (есть там полезный код или нет), поэтому я прописал Super.PostBeginPlay(); на всякий случай, чтобы не потерять какой-либо полезный код, если он вдруг там окажется.
по поводу event PlayerTimeOut() { if (Health > 0) Died(None, 'Suicided', Location); }
Эвент - это обытие. которое вызывается из нативного кода. Отличие эвента от функции только в том, что функция вызывается ИЗ СКРИПТОВ, - а эвент принудительно из нативного кода. То есть является изнасилованием актера движком игры.
Классическим примером Эвента является тот же PostBeginPlay() который принудительно вызывается движком игры к каждому актеру после загрузки уровня. Но Эвент он в классе Actor, а в младших классах его начинают постепенно именовать функцией, намекая на то, что он унаследован от "старшего" класса.
В действительности никакой разницы между функцией и эвентом нет. Слово event пишут для того, чтобы вы понимали, что он вызывается не из ваших скриптов, а непосредственно из нативного кода движком игры.
Так вот: event PlayerTimeOut() принудительно вызывается в том случае, если в сетевой игре сервер слишком долго не может получить ответ от компьютера игрока в игре по сети - или у него комп завис, или провайдер разорвал соединение, или скорость интернета снизилась настолько что пакеты по сети "не проходят" или проходят медленно.
В этом случае игрок стоит по среди уровня как столб, и сервер не может с ним ничего сделать, поскольку не имеет с игроком связи и не знает, что тот пытается предпринять на своём локальном компьютере.
В этом случае, подождав положенное время, сервер посылает Pawn-у эвент PlayerTimeOut(), сообщающий, что игрок в сетевой игре перестал отвечать на запросы. В этом случае (ЕСЛИ ЗДОРОВЬЕ ПАВНА больше нуля) скриптовой движок убивает павн-а, чтобы тот не стоял столбом посреди уровня и не мешал другим игрокам. (а если здоровье павна меньше нуля - это означает, что он лежит в виде трупа и никому не мешает. Будет лежать в ввиде трупа до восстановления связи с игроком или до окончания матча).
Пройдя поиском по скриптам, можно видеть, что PlayerTimeOut ниоткуда не вызывается. Иными словами, он вызывается не из скриптов, а только движком игры из нативного кода.
Сообщение отредактировал Reborn - Вторник, 20 Декабрь 16, 00:23
Написав код:function PostBeginPlay() { SetTimer (1.0, true); }
Вы ПЕРЕЗАПИСЫВАЕТЕ эту функцию, и всё, что было в ней в старшмх классах (Object -> Actor -> Inventory -> Weapon -> TournamentWeapon -> SniperRifle) выполняться не будет. Это может привести к глюкам, если там было прописано что-то критически важное для игры.
Поэтому, используя функцию, которая уже есть в старших классах, пишут: function PostBeginPlay()
{ Super.PostBeginPlay(); SetTimer (1.0, true); }
ЦитатаGP ()
по сути переопределение. Тоесть если где-то выше в класе (Mutator или еще выше) что-то исполнялось в этой фукцыи, то оно больше исполнятса не будет, ибо в вашем коде его нет. Для этого и используетса Super,
Спасибо большое, теперь понял, а я и не знал, что, написав код в функции, можно перезаписать эту же функцию в родительском классе! Я думал движок всегда будет читать одну и ту же функцию в разных классах, если код в этих классах не противоречит друг другу. Все, теперь в каждую функцию, где можно добавлю строку с Super!
Видимо по этому у меня боты перестали пользоваться отбойным молотком для прыжков, хотя ботинки для прыжков также продолжают прекрасно использовать. ------------------------------------------------------ Добавил save config() в свой мутатор, чтобы в случае удаления игроком конфигурационного файла автоматом бы создавался новый с дефолтными настройками. Файл создается, но возник глюк с искажением звука в игре. Может этот код отжирает больше чем нужно оперативки, выделяемой игрой для звука? Может я неправильно записал?
Код
function PreBeginPlay() { Super.PreBeginPlay(); SaveConfig(); }
Сообщение отредактировал Gadavre - Вторник, 20 Декабрь 16, 12:36
Попробуйте раде эксперемента убрать SaveConfig(); из PreBeginPlay(); (вообще убрать PreBeginPlay()) и вставить SaveConfig(); в любую другую функцию, например тот же PostBeginPlay() или ModifyPlayer(Pawn Other).
PreBeginPlay() отличается от PostBeginPlay() тем, что PreBeginPlay() вызывается ДО загрузки актера на уровень, а PostBeginPlay() - после. Но, по идее, на звук ни одна из этих функций влиять не должна. PreBeginPlay() вообще очень глючная функция, поскольку работает с ещё не загруженным актером. По этой причине её стараются не использовать. Если ваши выводы правильные, (что я не могу проверить), получается, что сохранение конфигурации ещё не загруженного актера как то влияет на игровой движок в целом. Мне это сомнительно, но проверить я не могу.
Сообщение отредактировал Reborn - Вторник, 20 Декабрь 16, 16:11
Если ваши выводы правильные, (что я не могу проверить), получается, что сохранение конфигурации ещё не загруженного актера как то влияет на игровой движок в целом.
Записал SaveConfig() в PostBeginPlay() и искажение звука теперь не наблюдается. Записал сразу после Super.PostBeginPlay() перед SetTimer. Последовательность строкдумаю не играет роли?
Как Вы считаете , если увеличить переменную visibility для живого обьекта со 128 (по умолчанию) до 255 (макс. значение), то это как то может повлиять на геймплей? То есть, чтоб игрок видел бота более детально на большой дистанции? Я че то ничего не заметил... Проверено, если visibility равна нулю, то бот просто пробегает мимо игрока, как будто его нет. написал в ModifyPlayer.
Код
if (Other.bIsPawn) { Other.Visibility = 255; }
Сообщение отредактировал Gadavre - Вторник, 20 Декабрь 16, 19:32
1) По идее, последовательность в данном случае не имеет значения. 2) Насколько я понимаю, переменная visibility отвечает за "видимость" игрока ботом. То есть не за то, насколько игрок видит бота, а за то, насколько бот видит игрока. //How visible is the pawn? 0 = invisible. 128 = normal. 255 = highly visible.
Появление этой переменной связано с игрой Unreal1 и с девайсом Invisiblity, позволявшем игроку перемещаться "невидимым" за спиной монстров. Если верить комментариям в коде, visibility=255 должно сделать игрока более "привлекательным" для ботов, и (если visibility=255 стоит только на игроке) сделать игрока приоритетной мишенью для бота. (а в Ut2004 прямо прописано, что живой игрок является для бота приорететной мишенью).
GP, как правильно написать в тейкдемедж что бы объект не получал урон, а отражал. Например объекту наносится 100ед, а он эти 100 едениц выплескивает в радиус (число) вокруг себя?
Infinite War v5.0.2 construction UIP 2.0 - UIPP(UIP 2.1)
До какой детальности тебе надо? Я на память почти ничего уже не напишу, ибо долго залипю в других языках. В общем значит поросто в коде обьекта в переопределяеш функцыю TakeDamage и в ней пишеш hurt radius (...damage)) или for each radius actors {other.takedamage(...damage...)}, чтоб обьект не получал урон то Super.TakeDamage вызываеш с 0-м или уменьшеным уроном, радиусом, моментом и т.д. или вообще не вызываш (лучше вызвать, страдает функцыональность с левыми мутаторами)
А еще эт, я не пойму как сделать одну вещь.... Короче допустим накладываем силовой купол(статик меш) на танк и как сделать что бы танк стрелял сквозь купол, т.е. изнутри танк и все кто стоят под куполом стреляют сквозь него, а все что попадает со внешней стороны купола ударяется в этот купол.
Infinite War v5.0.2 construction UIP 2.0 - UIPP(UIP 2.1)
Очень сложно, чтоб роботало как надо нужно влазить в код всего оружея в игре. Например отключать купол на момент выстрала не вариант. Можно наоборот мониторить все что летит в радиусе и подрывать чужое, что не вариант с трейсами (хитскан).
Сообщение отредактировал GP - Понедельник, 27 Февраль 17, 00:47