Anylogic模型运行时修改3D对象缩放比例触发空指针异常
Anylogic中修改Agent内3D对象缩放比例的问题及解决方法
问题描述
使用Anylogic个人学习版(PLE)完成学校项目时,获取名为mycar的Agent中名为car的3D对象当前缩放比例有两种有效方法:
// 方法1:通过Agent获取 mycar.getScale(); // 方法2:直接访问Agent内的3D对象获取 mycar.car.getScale();
但修改缩放比例时遇到两类问题:
- 编译错误:尝试直接调用Agent的
setScale方法时报错
mycar newCar = new mycar(); newCar.setScale(0.5);
错误提示:
The method setScale(double) is undefined for the type mycar.
- 运行时空指针异常:尝试直接访问3D对象调用
setSize方法,编译通过但点击按钮触发时抛出异常
mycar newCar = new mycar(); newCar.car.setSize(0.5);
运行时提示:
Error while executing user action
java.lang.NullPointerException
For more details see Console
控制台完整错误栈:
java.lang.NullPointerException at gettingsize.Main.executeShapeControlAction(Main.java:435) at gettingsize.Main$4.action(Main.java:496) at com.anylogic.engine.presentation.ShapeControl.executeAction(Unknown Source) at com.anylogic.engine.presentation.ShapeButton.executeUserAction(Unknown Source) at com.anylogic.engine.gui.ExperimentHost.executeUserAction(Unknown Source) at com.anylogic.engine.internal.webserver.a.onAction(Unknown Source) at com.anylogic.executor.basic.rest.BasicAnimationSessionController.lambda$null$3(BasicAnimationSessionController.java:71) at com.anylogic.engin.internal.webserver.d.acceptToAnimationSvgSession(Unknown Source) at com.anylogic.executor.basic.rest.BasicAnimationSessionController.lambda$startController$4(BasicAnimationSessionController.java:71) at spark.ResponseTransformerRouteImpl$1.handle(ResponseTransformerRouteImpl.java:47) at spark.http.matching.Routes.execute(Routes.java:61) at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:134) at com.anylogic.engine.internal.webserver.config.ALServerFactory$1.lambda$0(Unknown Source) at org.eclipse.jetty.servlets.QoSFilter.doFilter(QoSFilter.java:202) at com.anylogic.engine.internal.webserver.config.ALServerFactory$1.doHandle(Unknown Source) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1584) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) at org.eclipse.jetty.server.Server.handle(Server.java:501) at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383) at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105) at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:375) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938) at java.base/java.lang.Thread.run(Thread.java:834)
原因分析
- 编译错误:
mycarAgent类本身未定义setScale(double)方法,getScale()能生效是因为Agent继承的父类包含该读取方法,但修改缩放的操作必须直接作用于3D对象,而非Agent本身。 - 空指针异常:直接用
new mycar()创建Agent实例时,Anylogic引擎尚未初始化Agent内部的3D对象car,此时car为null,调用其方法自然会抛出异常。Agent及其内部组件必须通过引擎提供的方法生成,才能完成初始化。
解决方案
步骤1:正确初始化Agent实例
不要直接用new mycar()创建Agent,而是通过Anylogic自动生成的方法添加到模型中,例如:
// 方式1:从已有的Agent Population中获取实例 mycar existingCar = mycarPopulation.get(0); // 取Population中的第一个实例 // 方式2:创建新实例并添加到模型指定位置 mycar newCar = add_mycar(10, 10, 0); // x/y/z为3D空间中的放置坐标
步骤2:调用3D对象的setScale方法修改缩放
Agent初始化完成后,直接访问内部3D对象调用setScale方法(注意3D对象的缩放方法是setScale而非setSize):
// 统一设置XYZ三轴缩放比例为0.5 newCar.car.setScale(0.5); // 单独设置各轴缩放比例 // newCar.car.setScale(0.5, 0.6, 0.7);
优化方案:封装自定义方法
如果需要频繁修改缩放,可以在mycar Agent内部添加自定义方法,封装对3D对象的操作,同时增加空指针判断:
// 在mycar Agent的代码区域添加 public void setCarScale(double scale) { if (car != null) { car.setScale(scale); } }
之后可以直接调用Agent的自定义方法:
newCar.setCarScale(0.5);
内容的提问来源于stack exchange,提问作者Ali Zee Shan
相关产品推荐
相关产品推荐

