【游戏技术群】959392658  【游戏出海群】12067810
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

问答求助

关注:573

当前位置:游戏蛮牛 技术专区 问答求助

_____________________________________________________________________________________________________________
问答求助版块规则:

  1、问题尽量描述清楚
      2、代码要放在代码块里
      3、附件最好放到云盘,然后把链接放到TXT文档里,上传TXT文档。【最好没有附件,你懂得】
      4、本版块回复不得无意义,如:顶、呵呵、不错......以及擦边!【真的会扣分的哦】严重者,封IP!
      5、问题得到解决,请选择最佳答案。
      6、若问题是你自己解决了,可以联系管理员,返还蛮牛币,写下你的答案,另有蛮牛币奖赏。
_____________________________________________________________________________________________________________
查看: 1299|回复: 24

[脚本] 如果 对一个链表同时做 插入和删除操作

[复制链接]  [移动端链接]
6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
发表于 2018-11-5 15:01:45 | 显示全部楼层 |阅读模式
10蛮牛币
public List<Plate> plateList = new List<Plate>();  我创建一个 list 然后在update 里面不停的 插入和遍历数据,然后同时 不停的删除数据,  插入和删除的 速度不同,  这时候就会偶尔出现ArgumentOutOfRangeException: Argument is out of range.Parameter name: index  报错提示, 我的遍历方式是
for (int i = 0; i < plateList.Count; i++)
        {
            float dis = Vector2.Distance(plateList[i].pos, pos);
            if (dis <= posDistance)
            {
                return;
            }
        }

我理解是  在某一帧 遍历 时候, 恰好 plateList[i] 被删除了。 所有就出现报错 ,   哪位大佬说下 如何才能避免出错呀。 或者有什么好的方式 ,可以同时对一个链表 进行  插入,删除 和遍历操作。


回复

使用道具 举报

排名
720
昨日变化
2

17

主题

1153

帖子

3392

积分

Rank: 9Rank: 9Rank: 9

UID
68430
好友
13
蛮牛币
12346
威望
0
注册时间
2015-1-14
在线时间
918 小时
最后登录
2019-1-21
发表于 2018-11-5 15:01:46 | 显示全部楼层
两个方法粗略的写一下哈~~
方法1>
void update()
{
new 新列表 deleList;


for(你原本列表)
{
    if(执行条件满足)
       执行你的正经事情



    if(删除条件满足)
       deleList.add(条目);
}


for(便利deleList)
{
    原列表.remove(条目)
}
}
你看这样子,会产生越界吗?不会的~~


方法2> 利用MonoBehaviour生命周期 update 跟 lateupdate  执行差(非时间差哦,这仍然是同一帧)
void update()
{
for(你原本列表)
{
    if(执行条件满足)
       执行你的正经事情

}

}


void lateupdate ()
{
for(你原本列表)
{
    if(删除条件满足)
       原列表.remove(条目)

}

}



总结一下:方法1,利用临时列表暂时存储需要删除的条目,在执行正常循环完毕后,从原本列表内删除存储的条目,这样避免越界的
方法2,利用MonoBehaviour生命周期 update 跟 lateupdate  执行差,两个update 内各自执行一套相互不影响的循环,并执行将删除操作分割,这种方法也能避免越界~


希望能帮到你


点评

很强,赞!  发表于 2018-11-6 15:56

回复

使用道具 举报

5熟悉之中
710/1000
排名
4064
昨日变化
4

0

主题

37

帖子

710

积分

Rank: 5Rank: 5

UID
252114
好友
0
蛮牛币
549
威望
0
注册时间
2017-11-2
在线时间
307 小时
最后登录
2019-1-2
发表于 2018-11-5 15:55:29 | 显示全部楼层
遍历数组前,拿一个新列表用来遍历,遍历后更新这个新列表。保证此次遍历时列表长度不会有变化。或者写一个遍历方法,一个列表一旦开始遍历就不执行删除增加的操作,遍历完后调用删除增加的方法更新列表

回复

使用道具 举报

6蛮牛粉丝
1107/1500
排名
3456
昨日变化
1

5

主题

299

帖子

1107

积分

Rank: 6Rank: 6Rank: 6

UID
234410
好友
2
蛮牛币
1118
威望
0
注册时间
2017-7-26
在线时间
367 小时
最后登录
2019-1-18
发表于 2018-11-5 16:19:37 | 显示全部楼层
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i++)

回复

使用道具 举报

2初来乍到
135/150
排名
16725
昨日变化
7

0

主题

25

帖子

135

积分

Rank: 2Rank: 2

UID
143473
好友
0
蛮牛币
236
威望
0
注册时间
2016-3-25
在线时间
52 小时
最后登录
2018-12-24
发表于 2018-11-5 16:51:51 | 显示全部楼层
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的count,是return或break,否就继续;

回复

使用道具 举报

6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
 楼主| 发表于 2018-11-5 19:42:50 | 显示全部楼层
随幻Kaller 发表于 2018-11-5 16:19
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i ...

正是因为数目是 删之前的, 所有导致遍历时候 删除,导致越界的

回复

使用道具 举报

6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
 楼主| 发表于 2018-11-5 19:43:52 | 显示全部楼层
秋秋秋秋秋水 发表于 2018-11-5 15:55
遍历数组前,拿一个新列表用来遍历,遍历后更新这个新列表。保证此次遍历时列表长度不会有变化。或者写一个 ...

链表中的数组是根据时间自动删除的。 也就是链表中每个物体计时器到时间,自己删除,这个怎么控制
[发帖际遇]: 一个袋子砸在了 刘彦磊 头上,刘彦磊 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
 楼主| 发表于 2018-11-5 19:45:07 | 显示全部楼层
MaxSong 发表于 2018-11-5 16:51
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的c ...

你的第一种方法再详细解释下。 没明白

回复

使用道具 举报

6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
 楼主| 发表于 2018-11-5 19:46:40 | 显示全部楼层
随幻Kaller 发表于 2018-11-5 16:19
如果单纯的只是为了防止被删除影响数目 何不这样
int len = plateList.Count;
for (int i = 0; i < len ; i ...

记录数量这个不行的。 因为我是在遍历过程中删除的数据,导致链表变化了。所以才越界的

回复

使用道具 举报

6蛮牛粉丝
1287/1500
排名
3292
昨日变化
1

47

主题

423

帖子

1287

积分

Rank: 6Rank: 6Rank: 6

UID
149133
好友
19
蛮牛币
1138
威望
0
注册时间
2016-5-19
在线时间
375 小时
最后登录
2019-1-18
 楼主| 发表于 2018-11-5 19:48:40 | 显示全部楼层
MaxSong 发表于 2018-11-5 16:51
方法一:利用Unity脚本的生病周期进行List的增删遍历
方法二:遍历的时候判断一下当前i是否大于等于List的c ...

for (int j = 0; j < LastIdDic.Length; j++)
                    {
                          if(i>=LastIdDic.Count)
                              return;
                        if (LastIdDic[j]!=null)
                        {
                            if (LastIdDic[j].obj == plateObj)
                            {
                                LastIdDic[j] = null;
                            }
                        }                        
                    }

第二种方法是这样吗??

回复

使用道具 举报

7日久生情
2035/5000
排名
1594
昨日变化
6

19

主题

470

帖子

2035

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
218268
好友
5
蛮牛币
2376
威望
0
注册时间
2017-4-18
在线时间
748 小时
最后登录
2019-1-21

活力之星

发表于 2018-11-6 08:43:58 | 显示全部楼层
你可以试试while循环,做一个index时刻与count对比,超过了就跳出。不知道可以解决不

回复

使用道具 举报

6蛮牛粉丝
1107/1500
排名
3456
昨日变化
1

5

主题

299

帖子

1107

积分

Rank: 6Rank: 6Rank: 6

UID
234410
好友
2
蛮牛币
1118
威望
0
注册时间
2017-7-26
在线时间
367 小时
最后登录
2019-1-18
发表于 2018-11-6 09:24:42 | 显示全部楼层
刘彦磊 发表于 2018-11-5 19:46
记录数量这个不行的。 因为我是在遍历过程中删除的数据,导致链表变化了。所以才越界的 ...

这个不是链表 是列表
你可以将要删除的索引存起来 然后循环之后 统一从后往前删除
还有 在循环中删除本体本来就是不必要的 所以设计上也可以适当修改
[发帖际遇]: 随幻Kaller 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
710/1000
排名
4064
昨日变化
4

0

主题

37

帖子

710

积分

Rank: 5Rank: 5

UID
252114
好友
0
蛮牛币
549
威望
0
注册时间
2017-11-2
在线时间
307 小时
最后登录
2019-1-2
发表于 2018-11-6 09:28:48 | 显示全部楼层
我觉得每个物体计时器到时间,自己删除,然后同时还要一直遍历有点困难啊,可以统一写个每隔一段时间后先遍历,然后是增加删除的方法,就是每个物体自己的计时,如果到时间了,删掉然后更新等隔一段时间再从新遍历

回复

使用道具 举报

7日久生情
2954/5000
排名
512
昨日变化
1

2

主题

136

帖子

2954

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
121784
好友
0
蛮牛币
9495
威望
0
注册时间
2015-9-9
在线时间
1304 小时
最后登录
2019-1-21
发表于 2018-11-6 09:35:52 | 显示全部楼层
请使用ToArray将List转为数组(本质是复制操作),然后遍历这个数组

回复

使用道具 举报

6蛮牛粉丝
1019/1500
排名
13793
昨日变化
3

5

主题

194

帖子

1019

积分

Rank: 6Rank: 6Rank: 6

UID
26011
好友
0
蛮牛币
1396
威望
0
注册时间
2014-5-21
在线时间
757 小时
最后登录
2019-1-21
发表于 2018-11-6 11:31:43 | 显示全部楼层
多线程。lock锁。一个线程删,一个线程增。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表