Open GoogleCodeExporter opened 9 years ago
已知问题:
1. HoldPosition还没有实现
2. AttackToPosition / AttackAtDirection 还没有实现
3. AttackData.ScriptObjectAttachToTarget
还没有使用(因为还没有看见有这个需求)
Original comment by yinyuanq...@gmail.com
on 4 Jan 2013 at 11:38
AttackData.ScriptObjectAttachToTarget其实本来有用,就是那个减速枪
我已经改写成一个Component了,不过这个只能针对predator
如果以后把predator和AI都改成基于同一个底层,那就可以用在两
者身上了
另外,相对的,应该考虑加入ScriptObjectAttachToSource这样的东西
Original comment by lightnin...@gmail.com
on 6 Jan 2013 at 2:43
关于AI和Unit的关系:
现在的Unit不是一个Monobehavior,只是一个普通的类,并且是AI的一
个成员.相当于是一个纯粹的数据封装.
这样有一个问题,就是无法使用
GetComponent<Unit>去获取单位,而只能通过GetComponent<AI>().Unit获取Un
it,于是Unit只对AI有意义,对玩家单位而言没有意义.
所以带来一个改动:
Unit将是一个独立的Monobehavior而不只是AI的一个成员.
这样做对于Decal system也有意义,decal
system可以直接通过GameObjecr的Unit组件去获知这个单位的属性.
Original comment by yinyuanq...@gmail.com
on 8 Jan 2013 at 5:59
把Unit做成一个独立的Monobehavior也可以同时解决上一帖中Jeffery
提到的问题 - 用一个Unit类去统一AI和玩家单位的接口.
Original comment by yinyuanq...@gmail.com
on 8 Jan 2013 at 6:01
SVN改动已提交
UnitData.cs - 原来的Unit.cs中所有的类除了Unit都放到这个文件中
AISystem/Common/Unit.cs - 独立定义Unit (monobehavior)
Original comment by yinyuanq...@gmail.com
on 8 Jan 2013 at 6:08
可能不需要这么麻烦,因为这些减速之类的效果,影响的只是最
终结果,而不是原始的MoveData
PS:
ReceiveDamage部分,玩家单位已经在用unithealth,没什么问题
但是攻击(造成伤害)部分,目前就没有什么办法修改这个参数
Original comment by lightnin...@gmail.com
on 8 Jan 2013 at 6:38
AttackData.ScriptObjectAttachToTarget不应该是MonoBehaviour类型
给一个GameObject增加一个组件的办法似乎只有用AddComponent,只需
要class name
或者直接强类型添加一个,好像没办法添加一个已经实例化的M
onoBehaviour
(其实我之前写Weapon的时候也想把MonoBehaviour做成一个字段什么
的,不过没有达到想要的效果)不知道Editor有没有一些特殊的功
能...
既然写成了MonoBehaviour类型,我就暂时用这个做了一个减速和持
续伤害的效果的script
(我这个还是不导出unitypackage好了..附件里面包含场景文件和��
�个效果的script(放到weapon文件夹里面把),以及测试用的AttackData
.ScriptObjectAttachToTarget功能)
Original comment by lightnin...@gmail.com
on 8 Jan 2013 at 12:04
Attachments:
- AttackData.ScriptObjectAttachToTarget不应该是MonoBehaviour类型
呵呵,我想的恰恰相反,ScriptObjectAttachToTarget
应该是一个专门用于操作Unit属性的MonoBehavior.
做了这一段时间的Unity的开发,
感觉Unity编程最重要的,是数据封装,或者说数据结构定义.这里
的本质就是,你做为一个开发者,你怎样解析,你要实现的功能.
由于Unity编程需要考虑动画,时间,事件等等许多因素,
所以数据结构定义得好,你的代码就越灵活,能兼容的功能就越
多,拓展起来就更容易.
回到这个case上来,为什么ScriptObjectAttachToTarget要定义成一个Mono
behavior? 因为这样做最能和当前"Unit掌管数据,
AI掌管行为"的结构结合起来.
Unit掌管数据,所以,当我要改动一个单位的属性,例如,减速的时
候,我就只需要在Unit类上做改动,而不用去管AI会怎么工作.
这也是为什么我要把Unit从AI独立出来.
那么,当设计一个减速效果的ScriptObjectAttachToTarget类时,这个类�
��做的事情,就非常简单了,只需要把Unit的MoveData减低,然后再慢
慢提升. 这里还要做一个小改动,
Unit要加入一个SpeedModifier,MoveData计算速度的时候,MoveData.Speed *
SpeedModifier.
这样,减速的脚本只需要修改这个SpeedModifier就可以了.
Original comment by yinyuanq...@gmail.com
on 8 Jan 2013 at 1:58
可能你没看完我说的
你想做的和我想做其实是一样的
都是想用一个MonoBehavior或者说一个script去操作这个单位
但是要知道,这在Inspector上赋值的是一个已经实例化的脚本,没
有办法把这个放到其他对象里面去,如果要用MonoBehavior类型,那
么AddComponent之后就必须要重新把加在那个游戏对象的组件上,�
��新赋值
这和直接把脚本拖到游戏对象上是有不同的..你试试就知道了
Original comment by lightnin...@gmail.com
on 8 Jan 2013 at 2:05
这个问题先暂时hardcode 一个固定的值在脚本中吧,
以后等开始难度级别设计的时候再来考虑这个问题.
用PlayerPrefs 类应该可以解决这个问题:
If LevelManager.difficulty == Easy
PlayerPrefs.SetFloat("DecelerateFactor", 1.0f);
If LevelManager.difficulty == Middle
PlayerPrefs.SetFloat("DecelerateFactor", 1.5f);
减速脚本里面使用这个 PlayerPrefs.getfloat("DecelerateFactor")
用全局变量统一这些运行时添加的脚本的参数.
Original comment by yinyuanq...@gmail.com
on 8 Jan 2013 at 2:21
bugs
1.BiochemicalTrooper的Fire Behavuer结束条件,应该是always
true,否则目标一旦进入dectective range就永远无法执行其他行为
2.AIValueComparisionCondition.BehaviorLastExecutionInterval这个condition应该
是ShouldCompare=true的,但是没有设置.而且执行次数为0的时候这��
�条件应该直接就是true
Original comment by lightnin...@gmail.com
on 14 Jan 2013 at 4:17
另外,只能2个条件的组合,可能有点少(目前暂时够用)
我加了一个晕眩(无伤害)的攻击给AI
Original comment by lightnin...@gmail.com
on 14 Jan 2013 at 4:40
Attachments:
https://docs.google.com/file/d/0B6yPKfIXOM7PZmVaNHlBUXpBLTQ/edit
apk已经传至google drive
Original comment by lightnin...@gmail.com
on 14 Jan 2013 at 4:49
对AI框架又做了一些调整,Jeffery有时间UPDATE一下代码,
有些结构变了:
1. AI类不再继承于UnitHealth类.
2. 新增UnitBase类,UnitBase继承UnitHealth类.
类结构现在如下:
1. UnitHealth
提供(而不是封装)最基本的生命值获取方法.UnitHealth的本质就�
��一个接口,只不过U3D中无法通过GetComponent()获取结构,所以才��
�UnitHealth 定义成MonoBehavior的子类.
2. UnitBase
封装最基本生命值和一些LayerMask属性.以及新加入的两个属性:
public float SpeedModifier = 1; //减速器的那个通用属性
//盔甲类型
public ArmorType Armor = ArmorType.NoArmor_Human;
盔甲类型,这是从魔兽争霸III单位编辑器抄过来的一个设定.
暂时想到的就是用来约束声音. 比如说, ArmorType.NoArmor_Human
这个值的单位,在收到 DamageForm =
Predator_Single_Claw的伤害的时候,
GlobalAudioManager就会根据这个盔甲类和伤害类去检索对应的声��
� 然后播放.
3. 然后, Unit 继承与UnitBase类,
Predator3rdPersonalUnit也是继承于unitbase类,这样就把玩家单位和NPC
单位统一起来了. 它们都衍生于UnitBase类,
但是有各自的数据封装方法(MoveData, AttackData..等等)
Original comment by yinyuanq...@gmail.com
on 14 Jan 2013 at 6:27
Comment 11 by project member lightning.X.revenant, Today (2 hours ago)
bugs
1.BiochemicalTrooper的Fire Behavuer结束条件,应该是always
true,否则目标一旦进入dectective range就永远无法执行其他行为
2.AIValueComparisionCondition.BehaviorLastExecutionInterval这个condition应该
是ShouldCompare=true的,但是没有设置.而且执行次数为0的时候这��
�条件应该直接就是true
Delete comment
Comment 12 by project member lightning.X.revenant, Today (106 minutes ago)
另外,只能2个条件的组合,可能有点少(目前暂时够用)
我加了一个晕眩(无伤害)的攻击给AI
这些BUG将来会慢慢解决.
只有2个组合条件的原因是,这个框架只应用于基础的AI,而对更
加丰富的组合的情况, 需要: 自定义一个 AIEliteSoldier类,
然后这个AIEliteSoldier有新的ConditionData,例如EliteCOnditionData,这个
EliteCOnditionData提供了更多的组合条件,
然后AIEliteSoldier则基于这个条件编码.
Original comment by yinyuanq...@gmail.com
on 14 Jan 2013 at 6:31
bugs:
projectile的判定有问题,只要撞上任何一个物体,就能对指定目��
�造成伤害
我刚好把那个晕眩改成projectile形式的攻击
我已经fix了,顺便加入了一个callback,当projectile击中以后会往Src
.SendMessage(附带参数:击中的目标)
apk is uploading
Original comment by lightnin...@gmail.com
on 14 Jan 2013 at 1:25
Attachments:
1. 我觉得调用 Stun 的过程过于迂回了, Projectile命中 ->
通过设置 public string[] MessagesOnHit;
再调用Stun类的OnProjectileHit消息 . 这样,就需要: 1.
要在Inspector中配置MessagesOnHit,
2.要在Stun中添加一个OnProjectileHit(IEnumerable<GameObject>
targets)方法.
这个调用链条的点太多了. 为何不改成这样:
在Projectile中加入一个:
public MonoBehavior[] debuff; 在Inspector中指定Stun脚本
然后在DoDamage()中,直接AddComponent<debuff>
Stun则是:
void Start()
{
AI = GetComponent<AI>();
//do something
OnProjectileHit();
}
2. 另外,
bugs:
projectile的判定有问题,只要撞上任何一个物体,就能对指定目��
�造成伤害
这里,Projectile的判定是有BUG,但是你找到的这个应该不是BUG.
因为不是对指定目标造成伤害,而是对被撞上,同时又处于Attack
able层的物体造成伤害.
原来的代码是:
void OnTriggerEnter(Collider other)
{
HitSomething = true;
if (Util.CheckLayerWithinMask(other.gameObject.layer, this.AttackableLayer))
{
Target = other.gameObject;//如果撞上某物,切该物属于可攻击层,则选为目标
}
public virtual void DoDamage()
{
switch (this.AttackType)
{
case ProjectileAttackType.SingleTarget:
if (Target != null)//如果Target非空则发送HIT MESSAGE
{
Target.SendMessage("ApplyDamage", DamageParameter);
}
这一段其实是没有问题的. 这样想:
我希望机枪里打出的子弹, 既可以伤害玩家,也可以伤害人类,
所以,每颗子弹只需要把它的attackable layer设为human +
xenz就可以了,于是它打出时的Target设为Predator,但是真正的Target
是哪个,则是在OnTriggerEnter()方法里判定.按照你的改动,
只有HitObject == Target才发送HitMessage,
那么这个子弹就打不到所有非Target对象了:
if (HitObject == Target)
{
Target.SendMessage("ApplyDamage", DamageParameter);
targets.Add(Target);
}
真正的BUG应该是:
对于直线飞行的Projectile,当前的脚本没有考虑到射弹永远也无
法命中Target的情况.
例如,一颗子弹直线飞行,但是被玩家躲过了,
这样当过了数秒后,Launch脚本就会执行到DoDamage()方法,但是,
这个时候Target依然不为空(还是发射时指定的Target)
,于是,玩家照样中枪....
所以,需要在脚本考虑怎样加入这一段逻辑.
Original comment by yinyuanq...@gmail.com
on 14 Jan 2013 at 2:23
刚才又看了一遍, 发现之前看少了一行:
HitObject = other.gameObject;
楼上问题#2 不成立. 提交的代码在目标命中修复上没有问题.
Original comment by yinyuanq...@gmail.com
on 14 Jan 2013 at 2:52
1.这个问题其实就是ScriptObjectAttachToTarget的问题...(根本就没有
做这部分嘛)
2.
不如用一个实际例子说吧,我都测试了这么多遍了
不需要撞到其他东西,撞墙就好了
当物体撞到bridge
HitSomething = true;//projectile停止移动,然后DoDamage
if (Util.CheckLayerWithinMask(other.gameObject.layer, this.AttackableLayer))
{
Target = other.gameObject;//如果撞上某物,切该物属于可攻击层,则选为目标
}
//这个部分,条件不成立,所以不执行,target还是那个target,没有��
�化(PS:Target在AI.CreateProjectile方法里面被赋值为CurrentTarget.gameOb
ject)
然后跳到DoDamage()
因为
if (Target != null)//如果Target非空则发送HIT MESSAGE
这一个条件只是判断目标是不是存在,所以不管碰到是什么,照
样给原定的Target造成伤害
实际上嘛...一定成立的....除非 CurrentTarget.gameObject被destroy
我不止在if (HitObject == Target)动了手脚
我也在OnTriggerEnter那边加了一句, HitObject =
other.gameObject;(不然怎么来的HitObject啊!)
如果打到的是NPC,如果NPC也在AttackableLayer里面,那么就会先Target
= other.gameObject
然后HitObject = other.gameObject;
再去做if (HitObject == Target)判断(这肯定是成立的)
其实你想要的"躺着也中枪"的效果依然存在
Original comment by lightnin...@gmail.com
on 14 Jan 2013 at 2:55
ScriptObjectAttachToTarget
改成string或者TextAsset或者System.Type就可以了
然后AIEditor做相应的修改
在EditorCommon.cs的EditAttackData方法接近最后的地方
1.改成Type类型的话
Editor相应代码改成
MonoScript scriptValue = null;
if (AttackData.ScriptObjectAttachToTarget != null)
scriptValue=MonoScript.FromScriptableObject(ScriptableObject.CreateInstance(AttackData.ScriptObjectAttachToTarget));
var field = EditorGUILayout.ObjectField(new GUIContent("Script attach to FetchDamageSource:", "造成伤害时,自动附加该脚本组件."), scriptValue, typeof(MonoScript), false);
AttackData.ScriptObjectAttachToTarget = field == null ? null : ((MonoScript)field).GetClass();
2.改成string
MonoScript scriptValue = null;
if (AttackData.ScriptObjectAttachToTarget != null)
scriptValue=MonoScript.FromScriptableObject(ScriptableObject.CreateInstance(AttackData.ScriptObjectAttachToTarget));
var field = EditorGUILayout.ObjectField(new GUIContent("Script attach to FetchDamageSource:", "造成伤害时,自动附加该脚本组件."), scriptValue, typeof(MonoScript), false);
AttackData.ScriptObjectAttachToTarget = field == null ? null : ((MonoScript)field).name;
3.改成TextAsset的话...似乎会遇到一点问题,unity好像把TextAsset看
成是string.
不怕麻烦的话还是可以和上面一样的改
以上几种方法都可以直接AddComponent了,Editor上也可以正确的选�
��本
唯一的问题就是没办法设定脚本的值(还是之前说那个PlayerPref
s先把)
Original comment by lightnin...@gmail.com
on 16 Jan 2013 at 8:52
AI.cs1065行一处BUG:
原:
foreach (Collider c in Physics.OverlapSphere(transform.position, attackData.HitTestDistance, Unit.EnemyLayer))
{
StartCoroutine(SendHitmessage(CurrentTarget.gameObject, attackData));
}
中间那句改成StartCoroutine(SendHitmessage(c.gameObject, attackData));
Original comment by lightnin...@gmail.com
on 25 Jan 2013 at 2:24
Util.GetTopestParent不必这么麻烦,直接return transform.root;
http://docs.unity3d.com/Documentation/ScriptReference/Transform-root.html
Original comment by lightnin...@gmail.com
on 27 Jan 2013 at 7:40
AttackData.ScriptObjectAttachToTarget可以考虑修改成AttackData.ObjectAttac
hToTarget
一方面可以脚本也可以配置
还能附加一些特效
Original comment by lightnin...@gmail.com
on 27 Jan 2013 at 7:49
AI framework改动:
I_AIBehaviorHandler.cs
Projectile.cs
AI.cs
基础AI接口方法改动:
基础接口删除 AlterBehavior方法,增加 StartAI/StopAI方法.
Projectile.cs 命中BUG改动,见之前Jeffery的COMMENT #16.
Original comment by yinyuanq...@gmail.com
on 1 Feb 2013 at 8:30
对AI 框架做出一些改动, 已提交SVN:
1.Editor改动:
a.Assets\Scripts\AISystem\Editor\AIEditor.cs和Assets\Scripts\Editor\EditorCommo
n.cs这两个类装载编辑AI的公用方法.
b.Editor界面则分离到 Assets\Scripts\AISystem\Editor\AIEditorWindow.cs 和
AIInspector.cs 中.
2. AI.cs改动:
a. A*Pathfind相关函数改动.
只在当前对象不可见的情况下使用A*Pathfind 系统.
b. IdleData加入几个参数,
是否在Idle的时候保持面朝向当前目标(CurrentTarget)
c. AIBooleanConditionEnum - Boolean判断条件类,加入 LatestBehaviorNameIs
和 LastestBehaviorNameIsOneOf
两种,如果当前正在执行的行为名字叫XXX或者是
{XXX,YYY,ZZZ}之一的时候, 执行判断.
另外,即将进行的下一个改动,是让AI可以并行工作.例如,一个Ga
meObject上同时有三个AI组件,一个组件负责移动,另一个组件负��
�攻击, 第三个组件负责攻击间隔期间的摇摆行为.
这就需要一个类似AIManager的类,负责在三个AI组件之间进行调��
�.
Original comment by yinyuanq...@gmail.com
on 9 Feb 2013 at 4:50
AI 框架改动, 已提交SVN:
主要改动:
1.
对条件(ConditionData)系列的改动。现在支持多个条件组合了。
原本的ConditionData改名为AtomConditionData, 即原子条件。
增加CompositeConditionData, 复合条件,
复合条件可以引用其它的复合条件或者原子条件,用逻辑运��
�符 AND , OR组合,例如:
预定义三个原子条件:
原子条件ID 001 为: Enemy In Offensive Range = True,
原子条件ID 002 为: Enemy In Detective Range = False,
原子条件ID 003 为: Random Value <= 50
然后预定义两个复合条件:
Composite Condition ID001 = 001 : <Atom Condition 002> AND Atom <Condition 003>
Composite Condition ID002 = AtomCondition 001 OR CompositeConditionID 001
这样,复合条件CompositeCondition ID 002的表达式就是:
(Enemy In Offensive Range = True) OR (Enemy In Detective Range = False AND
Random Value <= 50)
具体定义见 CompositeConditionWrapper , CompositeCondition, AtomCondition.
旧的 AIBehaviorCondition 类 已经弃用。
在 Editor中添加一个专门编辑条件的窗口类
ConditionEditorWindow,在编辑AI的时候(AIEditor窗口或者Inspector),
编辑AIBehavior -> 点击 Edit Start Condition /Edit end condition
编辑条件。
2. 把 A* navigation 的功能从AI类移除,放到 AStarNavigator 类中。
这样做主要是为了多个AI组件并存。
3. ApplyDamage移除到AIApplyDamage中,
原因同样是为了多个AI组件并存,
4. 一些小的BUG FIX。
5. 引入 AIController 类(功能还未实现),
用于在数个AI之间调度AI的开/关。
6. 引入AIEventListener
类,用于处理各种事件,例如,动画事件。
Original comment by yinyuanq...@gmail.com
on 4 Mar 2013 at 2:28
最新的 AI.cs.....不会玩捉迷藏的士兵不是好AI
NavigateToTransform的结束条件与Start_Attack方法中执行攻击的条件�
��一致
中间隔着那些Obstacle层的东西就站着不动了
解决办法:
增加一个NavigateToTransform重载方法
public virtual IEnumerator NavigateToTransform(Transform TargetTransform,
MoveData moveData,
System.Predicate<Transform> BreakCondition)
{
...
while (TargetTransform != null &&
!BreakCondition(TargetTransform))
...
}
相应的Start_Attack方法的那部分改成
yield return StartCoroutine(NavigateToTransform(CurrentTarget,
moveData, tar => this.CanSeeCurrentTarget && CurrentTargetDistance <= attackData.AttackableRange));
Original comment by lightnin...@gmail.com
on 5 Apr 2013 at 10:36
#27 的楼指出的BUG已修正。
Original comment by yinyuanq...@gmail.com
on 19 Apr 2013 at 7:45
Projectile命中判断BUG:
对于身前具有"挡箭牌"的BOT,无法正常造成伤害
如Defenser-I,它的两个TriggerCollider都会有这种作用
修改:
OnTriggerStay与OnTriggerEnter增加对无效图层的判断
(在上面那个例子里面,无效图层是Ignore Raycast)
PS:可以考虑直接归类到LevelManager
Original comment by lightnin...@gmail.com
on 18 May 2013 at 6:22
To #29
这种情况,我认为合理的解决方案是在ProjectSetting ->
Physics里面,让 Collider 不与Projectile做碰撞校验. 问题的本质是,
挡箭牌Collider放错了层.
Original comment by yinyuanq...@gmail.com
on 20 May 2013 at 3:00
Reply #30
对喔,还有ProjectSetting -> Physics这个东西
我这的TriggerCollider在Ignore Raycast层,感觉好像没什么问题!?
Original comment by lightnin...@gmail.com
on 20 May 2013 at 3:14
UnitData的Clone改进:
看代码上面的GetClone方法,做的基本都是浅复制,所以不需要每�
��字段/属性都自己复制一次
.net框架有提供一个MemberwiseClone()的方法
另外我看数组也有一个专门的Util.CloneArray方法
实际上Array有实现ICloneable接口,而且实现的是也是和Util.CloneArr
ay一样的浅复制,所以也不用自己增加工作量了
另外建议这些Data直接实现System.ICloneable接口吧
Original comment by lightnin...@gmail.com
on 21 May 2013 at 3:11
bugs:
隐身之后AI不会丢失目标
AI找不到目标就原地站着不动(暂时加一个原地左右观望的动��
�和behavior好了)
Original comment by lightnin...@gmail.com
on 4 Jun 2013 at 5:10
bugs:
AI.cs的Start_MoveAtDirection方法内第一句
Vector3 direction = behavior.IsWorldDirection ? behavior.MoveDirection :
transform.InverseTransformDirection(behavior.MoveDirection);
按代码看,这个direction应该是世界坐标下面的方向
而Transform.InverseTransformDirection这个方法的作用是Transforms a
direction from world space to local space. The opposite of
Transform.TransformDirection(http://docs.unity3d.com/Documentation/ScriptRefer
ence/Transform.InverseTransformDirection.html)
显然搞错了。。。。
Original comment by lightnin...@gmail.com
on 4 Jun 2013 at 6:27
AI.cs
Start_SwitchToAI方法最后
还要再加一句
nextAI.StartAI();
否则不会执行新的AI
Original comment by lightnin...@gmail.com
on 14 Jun 2013 at 3:19
Original issue reported on code.google.com by
yinyuanq...@gmail.com
on 4 Jan 2013 at 8:39