Showing posts with label unity3d. Show all posts
Showing posts with label unity3d. Show all posts

Friday, September 14, 2018

Unity game white screen

Leave a Comment

I was using Unity 5.6.f, now I have upgraded to version 2018.2.6.

My game worked perfectly on my Samsung Edge 7, but now when I make a build, all I see is just a full white screen. I tried to change the settings and the camera properties but with no luck.

Note: My game used to start with background music but now I don't hear anything. Also the unity splash screen doesn't show up, there is just a blank white screen!

What should I do? What is wrong with my settings?

Here is my Logcat:

09-10 23:52:56.548 3659-3785/? D/SamsungAlarmManager: Expired : 8 09-10 23:52:56.548 3659-3785/? I/SamsungAlarmManager: setLocked to kernel - T:3 / 20180910T235300, SetElapsed=651150845, nowELAPSED=651147393 09-10 23:52:56.549 3659-3785/? V/SamsungAlarmManager: Sending to uid : 11220 action=null alarm=Alarm{4d8e547 type 1 when 1536612776547 com.dianxinos.optimizer.duplay} 09-10 23:52:56.559 3659-10166/? D/SamsungAlarmManager: Cancel Alarm calling from uid:11220 pid :1593 / op:PendingIntent{21f7174: PendingIntentRecord{bd8b994 com.dianxinos.optimizer.duplay startService}} 09-10 23:52:56.571 3659-10166/? D/SamsungAlarmManager: setInexact Intent (T:1/F:0/AC:false) 20180910T235316 - CU:11220/CP:1593 09-10 23:52:56.870 3659-10166/? E/memtrack: Couldn't load memtrack module 09-10 23:52:56.870 3659-10166/? W/android.os.Debug: failed to get memory consumption info: -1 09-10 23:52:57.019 3659-10166/? E/memtrack: Couldn't load memtrack module 09-10 23:52:57.019 3659-10166/? W/android.os.Debug: failed to get memory consumption info: -1 09-10 23:52:57.396 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=2 09-10 23:52:58.409 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=0 09-10 23:52:59.610 3659-21830/? D/BatteryService: !@BatteryListener : batteryPropertiesChanged! 09-10 23:52:59.611 3659-21830/? D/BatteryService: level:59, scale:100, status:2, health:2, present:true, voltage: 3976, temperature: 359, technology: Li-ion, AC powered:false, USB powered:true, POGO powered:false, Wireless powered:false, icon:17303851, invalid charger:0, maxChargingCurrent:0, maxChargingVoltage:0, chargeCounter:0     online:6, current avg:794, charge type:1, power sharing:false, high voltage charger:false, capacity:280000, batterySWSelfDischarging:false, misc_event:0, current_event:0, current_now:814 09-10 23:52:59.612 3659-3659/? D/BatteryService: Sending ACTION_BATTERY_CHANGED. 09-10 23:52:59.618 3659-3659/? I/MotionRecognitionService: Plugged 09-10 23:52:59.619 3659-3659/? I/MotionRecognitionService: connected - grip disable 09-10 23:52:59.628 4135-4135/? D/KeyguardUpdateMonitor: received broadcast android.intent.action.BATTERY_CHANGED 09-10 23:52:59.629 4135-4135/? D/BatteryController: onReceive-ACTION_BATTERY_CHANGED : mLevel=59, mBatteryStatus=2 09-10 23:52:59.640 4135-4135/? D/PowerUI: priorPlugType = 2 mPlugType =  2 09-10 23:52:59.647 3659-4661/? D/ConnectivityService: filterNetworkStateForUid() uid: 11220 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.652 4135-4135/? D/PowerUI.Notification: showChargingNotice oldChargingType : 1 currentChargingType : 1 oldChargingTime : 5516000 mChargingTime : 5501000 09-10 23:52:59.653 4135-4135/? D/PowerUI.Notification: showChargingNotification() 09-10 23:52:59.654 3659-4924/? D/ConnectivityService: filterNetworkStateForUid() uid: 11354 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.658 3659-5590/? D/ConnectivityService: filterNetworkStateForUid() uid: 11220 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.662 3659-4661/? D/ConnectivityService: filterNetworkStateForUid() uid: 11354 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.667 3659-4661/? D/ConnectivityService: filterNetworkStateForUid() uid: 10193 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.671 4135-4135/? D/Notification: allPendingIntents 09-10 23:52:59.673 3659-5667/? D/ConnectivityService: filterNetworkStateForUid() uid: 10193 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:52:59.676 3659-4924/? D/API test: getContainerInfo: value is      getContainerInfo: value is  09-10 23:52:59.707 3659-3659/? D/MotionRecognitionService:   mCableConnection= 1     clear SAR_DEVICE_GRIP (setPowerConnected)  09-10 23:52:59.708 3659-3659/? D/SamsungPhoneWindowManager: ACTION_BATTERY_CHANGED - Level :: 59, battStatus :: 2 09-10 23:52:59.708 3659-3801/? E/MotionRecognitionService: handleMessage: event 200 value : 1 09-10 23:52:59.710 3659-3689/? D/UsbDeviceManager: handleMessage -> MSG_UPDATE_CHARGING_STATE = 1 09-10 23:52:59.711 3659-3659/? D/EdgeLightingManager: isCallingUserSupported : callingUserId=-1, mUserId=0, isDualAppId=false 09-10 23:52:59.714 3659-3659/? D/AudioService: getStreamVolume 5 index 0 09-10 23:52:59.720 3659-4924/? D/Notification: allPendingIntents 09-10 23:52:59.721 3659-10166/? D/Notification: allPendingIntents 09-10 23:52:59.721 3659-5667/? D/Notification: allPendingIntents 09-10 23:52:59.727 5021-5021/? D/CatchNotificationsService: onNotificationPosted 09-10 23:52:59.728 3659-5667/? D/Notification: allPendingIntents 09-10 23:52:59.731 3659-4924/? D/Notification: allPendingIntents 09-10 23:52:59.732 3659-3801/? D/MotionRecognitionService: clear TransmitPower  value : 1     clear TransmitPower  value : 1 09-10 23:52:59.745 5087-25650/? D/BadgeProvider: query, [selection] : null 09-10 23:52:59.763 5021-5021/? E/CatchNotificationsService: Invalid notification data 09-10 23:52:59.797 4135-4135/? W/StaticLayout: maxLineHeight should not be -1.  maxLines:1 lineCount:1 09-10 23:52:59.800 4135-4135/? I/chatty: uid=10064(u0_a64) com.android.systemui identical 2 lines 09-10 23:52:59.801 4135-4135/? W/StaticLayout: maxLineHeight should not be -1.  maxLines:1 lineCount:1 09-10 23:52:59.805 5050-5070/? I/zygote64: Background concurrent copying GC freed 20115(989KB) AllocSpace objects, 0(0B) LOS objects, 66% free, 770KB/2MB, paused 21.115ms total 83.742ms 09-10 23:52:59.828 4135-4135/? W/StaticLayout: maxLineHeight should not be -1.  maxLines:1 lineCount:1 09-10 23:53:00.001 3659-3785/? D/SamsungAlarmManager: Expired : 8 09-10 23:53:00.002 3659-3785/? I/SamsungAlarmManager: setLocked to kernel - T:3 / 20180910T235316, SetElapsed=651167568, nowELAPSED=651150846 09-10 23:53:00.003 3659-3785/? V/SamsungAlarmManager: Sending to uid : 1000 action=android.intent.action.TIME_TICK alarm=Alarm{696712 type 3 when 651150845 android} 09-10 23:53:00.008 3659-3659/? D/SamsungAlarmManager: setExact Intent (T:3/F:1/AC:false) 20180910T235359 - CU:1000/CP:3659 09-10 23:53:00.010 4135-4135/? D/KeyguardUpdateMonitor: received broadcast android.intent.action.TIME_TICK 09-10 23:53:00.011 4135-4135/? D/KeyguardServiceBoxContainer: refreshTime() 1 09-10 23:53:00.594 3286-3286/? E/audit: type=1400 audit(1536612780.591:84424): avc:  denied  { read } for  pid=21505 comm=43707520436F6C6C656374696F6E name="stat" dev="proc" ino=4026534927 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0 SEPF_SM-G935F_8.0.0_0011 audit_filtered 09-10 23:53:00.630 4697-4697/? D/io_stats: !@   8,0 r 13057802 526259596 w 3460694 64451520 d 486779 24649384 f 938215 937809 iot 10758130 9080915 th 375916 0 0 pt 0 inp 0 0 210836.246 09-10 23:53:01.435 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=2 09-10 23:53:01.626 9154-9154/? D/Notification: allPendingIntents 09-10 23:53:01.641 9154-9154/? D/Notification: allPendingIntents 09-10 23:53:01.649 3659-3680/? D/API test: getContainerInfo: value is  09-10 23:53:01.655 3659-3659/? D/EdgeLightingManager: isCallingUserSupported : callingUserId=0, mUserId=0, isDualAppId=false 09-10 23:53:01.656 3659-3659/? D/EdgeLightingManager: showForNotification : isInteractive=true, isHeadUp=false, color=0, sbn = StatusBarNotification(pkg=com.dianxinos.optimizer.duplay user=UserHandle{0} id=439 tag=null key=0|com.dianxinos.optimizer.duplay|439|null|11220: Notification(channel=null pri=2 contentView=com.dianxinos.optimizer.duplay/0x7f040196 vibrate=null sound=null defaults=0x0 flags=0x62 color=0x00000000 number=0 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0)) 09-10 23:53:01.656 3659-3659/? D/EdgeLightingClientManager: isAvailableEdgeLighting: condition=1 mCondition=3 mIsConnected=false1 09-10 23:53:01.657 3659-3659/? D/EdgeLightingPolicyManager: isAcceptableApplication:  pkg=com.dianxinos.optimizer.duplay , range=256 , includeAllApp=false , userId=0 , infoRange=0 , infoCategory=0     putNotification tickerText:false,titleText:false,text:false,sub:falsecn= + null 09-10 23:53:01.658 3659-3659/? D/EdgeLightingPolicyManager.NotificationGroup: updateNotificationData put :0|com.dianxinos.optimizer.duplay|439|null|11220,size=3     0|com.dianxinos.dxbs|2|null|10193:NotificationData time=1536612769757,     0|com.dianxinos.optimizer.duplay|439|null|11220:NotificationData time=1536612781657,     0|com.duapps.antivirus|1024|DuScene|11354:NotificationData time=1536610136399, 09-10 23:53:01.658 3659-3659/? D/EdgeLightingManager: showForNotificationScreenOn : texts are empty. 09-10 23:53:01.673 3659-4924/? D/Notification: allPendingIntents 09-10 23:53:01.675 3659-10166/? D/Notification: allPendingIntents 09-10 23:53:01.677 3659-3659/? D/Notification: allPendingIntents 09-10 23:53:01.678 3659-4661/? D/Notification: allPendingIntents 09-10 23:53:01.681 5021-5021/? D/CatchNotificationsService: onNotificationPosted 09-10 23:53:01.685 3659-10166/? D/Notification: allPendingIntents 09-10 23:53:01.689 3659-5590/? D/Notification: allPendingIntents 09-10 23:53:01.698 5087-25650/? D/BadgeProvider: query, [selection] : null 09-10 23:53:01.708 5021-5021/? E/CatchNotificationsService: Invalid notification data 09-10 23:53:01.762 4135-4135/? D/swipe: !isFreemformEnabled 09-10 23:53:02.448 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=0 09-10 23:53:03.459 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=3 09-10 23:53:04.347 17576-17633/? I/System.out: (HTTPLog)-Static: isSBSettingEnabled false 09-10 23:53:04.348 17576-17633/? I/System.out: (HTTPLog)-Static: isSBSettingEnabled false 09-10 23:53:05.479 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=2 09-10 23:53:05.600 3286-3286/? E/audit: type=1400 audit(1536612785.591:84425): avc:  denied  { read } for  pid=21505 comm=43707520436F6C6C656374696F6E name="stat" dev="proc" ino=4026534927 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0 SEPF_SM-G935F_8.0.0_0011 audit_filtered 09-10 23:53:05.635 4697-4697/? D/io_stats: !@   8,0 r 13057802 526259596 w 3460709 64451608 d 486779 24649384 f 938219 937813 iot 10758140 9080919 th 375856 0 0 pt 0 inp 0 0 210841.252 09-10 23:53:06.507 3659-9981/? D/SSRM:O: SIOP:: AP = 390, PST = 388 (W:14), BAT = 359, CHG = 395, CP = 347 09-10 23:53:07.499 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=3 09-10 23:53:09.518 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=0 09-10 23:53:09.659 3659-5590/? D/ConnectivityService: filterNetworkStateForUid() uid: 10201 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.671 3659-21830/? D/BatteryService: !@BatteryListener : batteryPropertiesChanged! 09-10 23:53:09.672 3659-21830/? D/BatteryService: level:59, scale:100, status:2, health:2, present:true, voltage: 3975, temperature: 359, technology: Li-ion, AC powered:false, USB powered:true, POGO powered:false, Wireless powered:false, icon:17303851, invalid charger:0, maxChargingCurrent:0, maxChargingVoltage:0, chargeCounter:0     online:6, current avg:796, charge type:1, power sharing:false, high voltage charger:false, capacity:280000, batterySWSelfDischarging:false, misc_event:0, current_event:0, current_now:798 09-10 23:53:09.673 3659-3659/? D/BatteryService: Sending ACTION_BATTERY_CHANGED. 09-10 23:53:09.679 3659-3659/? I/MotionRecognitionService: Plugged     connected - grip disable 09-10 23:53:09.686 4135-4135/? D/KeyguardUpdateMonitor: received broadcast android.intent.action.BATTERY_CHANGED 09-10 23:53:09.694 4135-4135/? D/BatteryController: onReceive-ACTION_BATTERY_CHANGED : mLevel=59, mBatteryStatus=2 09-10 23:53:09.704 4135-4135/? D/PowerUI: priorPlugType = 2 mPlugType =  2 09-10 23:53:09.707 4135-4135/? D/PowerUI.Notification: showChargingNotice oldChargingType : 1 currentChargingType : 1 oldChargingTime : 5501000 mChargingTime : 5501000     There is no change about charging status, so return! 09-10 23:53:09.715 3659-21830/? D/ConnectivityService: filterNetworkStateForUid() uid: 11220 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.721 3659-21830/? D/ConnectivityService: filterNetworkStateForUid() uid: 11220 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.725 3659-21830/? D/ConnectivityService: filterNetworkStateForUid() uid: 11354 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.743 3659-21830/? D/ConnectivityService: filterNetworkStateForUid() uid: 10193 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.753 3659-5590/? D/ConnectivityService: filterNetworkStateForUid() uid: 10193 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.758 3659-5590/? D/ConnectivityService: filterNetworkStateForUid() uid: 11354 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:09.789 3659-3659/? D/MotionRecognitionService:   mCableConnection= 1     clear SAR_DEVICE_GRIP (setPowerConnected)  09-10 23:53:09.790 3659-3801/? E/MotionRecognitionService: handleMessage: event 200 value : 1 09-10 23:53:09.790 3659-3659/? D/SamsungPhoneWindowManager: ACTION_BATTERY_CHANGED - Level :: 59, battStatus :: 2 09-10 23:53:09.791 3659-3689/? D/UsbDeviceManager: handleMessage -> MSG_UPDATE_CHARGING_STATE = 1 09-10 23:53:09.796 3659-3801/? D/MotionRecognitionService: clear TransmitPower  value : 1     clear TransmitPower  value : 1 09-10 23:53:10.607 3286-3286/? E/audit: type=1400 audit(1536612790.601:84426): avc:  denied  { read } for  pid=21505 comm=43707520436F6C6C656374696F6E name="stat" dev="proc" ino=4026534927 scontext=u:r:untrusted_app_25:s0:c512,c768 tcontext=u:object_r:proc_stat:s0 tclass=file permissive=0 SEPF_SM-G935F_8.0.0_0011 audit_filtered 09-10 23:53:10.641 4697-4697/? D/io_stats: !@   8,0 r 13057802 526259596 w 3460710 64451620 d 486779 24649384 f 938220 937814 iot 10758140 9080920 th 373288 0 0 pt 0 inp 0 0 210846.257 09-10 23:53:11.537 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=2 09-10 23:53:11.690 3659-21830/? D/SamsungAlarmManager: Cancel Alarm calling from uid:10020 pid :4782 / op:PendingIntent{df2e25e: PendingIntentRecord{46a9627 com.google.android.gms broadcastIntent}} 09-10 23:53:11.709 3659-21830/? D/SamsungAlarmManager: setExact Intent (T:2/F:5/AC:false) 20180911T000711 - CU:10020/CP:4782 09-10 23:53:11.746 5187-5187/? I/GCM: Message from 745476177629 09-10 23:53:11.804 3659-3679/? D/ConnectivityService: filterNetworkStateForUid() uid: 1000 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:11.813 3659-3679/? D/ConnectivityService: filterNetworkStateForUid() uid: 10113 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:11.827 3659-3679/? D/ConnectivityService: filterNetworkStateForUid() uid: 1000 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:11.863 3659-3679/? D/StorageManagerService: getExternalStorageMountMode : 3     getExternalStorageMountMode : 3 09-10 23:53:11.864 3659-3679/? D/StorageManagerService: getExternalStorageMountMode : final mountMode=3, uid : 10113, packageName : com.google.android.gm 09-10 23:53:11.864 3659-3679/? D/ActivityManager: package  com.google.android.gm, user - 0 is SDcard whitelisted 09-10 23:53:11.887 3659-3679/? I/ActivityManager: Start proc 8294:com.google.android.gm/u0a113 for service com.google.android.gm/.provider.MailSyncAdapterService 09-10 23:53:11.887 8294-8294/? E/Zygote: isWhitelistProcess - Process is Whitelisted 09-10 23:53:11.887 3659-3679/? I/ActivityManager: Start proc 8294:com.google.android.gm/u0a113 for service com.google.android.gm/.provider.MailSyncAdapterService 09-10 23:53:11.889 8294-8294/? E/libpersona: scanKnoxPersonas     Couldn't open the File - /data/system/users/0/personalist.xml - No such file or directory 09-10 23:53:11.894 8294-8294/? W/SELinux: SELinux selinux_android_compute_policy_index : Policy Index[2],  Con:u:r:zygote:s0 RAM:SEPF_SM-G935F_8.0.0_0011, [-1 -1 -1 -1 0 1] 09-10 23:53:11.896 8294-8294/? I/SELinux: SELinux: seapp_context_lookup: seinfo=untrusted, level=s0:c512,c768, pkgname=com.google.android.gm  09-10 23:53:11.902 8294-8294/? I/zygote64: Late-enabling -Xcheck:jni 09-10 23:53:11.939 8294-8294/? D/TimaKeyStoreProvider: TimaKeyStore is not enabled: cannot add TimaSignature Service and generateKeyPair Service 09-10 23:53:11.940 8294-8294/? D/ActivityThread: Added TimaKeyStore provider 09-10 23:53:11.946 3659-5590/? I/ActivityManager: DSS on for com.google.android.gm and scale is 1.0 09-10 23:53:12.014 8294-8294/? I/zygote64: no shared libraies, dex_files: 1 09-10 23:53:12.192 8294-8294/? W/ComponentDiscovery: Application info not found.     Could not retrieve metadata, returning empty list of registrars. 09-10 23:53:12.320 8294-8294/? D/ActivityThread: Loading provider com.google.android.gm.sapi: com.google.android.gm.sapi.SapiUiProvider 09-10 23:53:12.441 3659-5590/? W/StorageManager: getStorageLowBytes lowPercent : 5, lowBytes : 1327564390, maxLowBytes : 524288000 09-10 23:53:12.453 8294-8294/? W/GAV2: Thread[main,5,main]: Need to call initialize() and be in fallback mode to start dispatch. 09-10 23:53:12.495 8294-8324/? I/PrimesTesting: GserviceFlagsSupplier.get() 09-10 23:53:12.544 4135-4372/? D/NetworkController.MobileSignalController(0/3): onDataActivity: direction=3 09-10 23:53:12.607 3659-3679/? D/ConnectivityService: filterNetworkStateForUid() uid: 1000 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:12.696 3659-4661/? D/ConnectivityService: filterNetworkStateForUid() uid: 10020 networkInfo: [type: MOBILE[LTE] - MOBILE, state: CONNECTED/CONNECTED, reason: (unspecified), extra: we, failover: false, available: true, roaming: false, metered: true] 09-10 23:53:12.781 3659-21830/? W/StorageManager: getStorageLowBytes lowPercent : 5, lowBytes : 1327564390, maxLowBytes : 524288000 

Here is my Menifest file:

    <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" package="com.example.admobtest" android:versionName="1.0" android:versionCode="1">   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />   <!-- Google Mobile Ads Permissions -->   <uses-permission android:name="android.permission.INTERNET" />   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />   <uses-permission android:name="com.android.vending.BILLING" />   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false">       <!-- meta-data tag for Google Play services -->     <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>     <activity android:name="com.unity3d.player.UnityPlayerProxyActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >       <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />       <intent-filter>         <action android:name="android.intent.action.MAIN" />         <category android:name="android.intent.category.LAUNCHER" />       </intent-filter>     </activity>     <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >     </activity>     <activity android:name="com.unity3d.player.UnityPlayerNativeActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >       <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />       <meta-data android:name="android.app.lib_name" android:value="unity" />     </activity>     <activity android:name="com.unity3d.player.VideoPlayer" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >     </activity>        <!-- Google Mobile Ads Activity -->     <activity android:name="com.google.android.gms.ads.AdActivity"               android:label="@string/app_name"               android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">     </activity>     <!--Added by ME on 01.09.14 23:17-->     <activity android:name="com.prime31.GoogleIABProxyActivity"></activity>       </application>   <uses-feature android:glEsVersion="0x00020000" />   <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="27" /> </manifest> 

0 Answers

Read More

Saturday, September 8, 2018

OpenGL drawing on Android combining with Unity to transfer texture through frame buffer cannot work

Leave a Comment

I'm currently making an Android player plugin for Unity. The basic idea is that I will play the video by MediaPlayer on Android, which provides a setSurface API receiving a SurfaceTexture as constructor parameter and in the end binds with an OpenGL-ES texture. In most other cases like showing an image, we can just send this texture in form of pointer/id to Unity, call Texture2D.CreateExternalTexture there to generate a Texture2D object and set that to an UI GameObject to render the picture. However, when it comes to displaying video frames, it's a little bit different since video playing on Android requires a texture of type GL_TEXTURE_EXTERNAL_OES while Unity only supports the universal type GL_TEXTURE_2D.

To solve the problem, I've googled for a while and known that I should adopt a kind of technology called "Render to texture". More clear to say, I should generate 2 textures, one for the MediaPlayer and SurfaceTexture in Android to receive video frames and another for Unity that should also has the picture data inside. The first one should be in type of GL_TEXTURE_EXTERNAL_OES (let's call it OES texture for short) and the second one in type of GL_TEXTURE_2D (let's call it 2D texture). Both of these generated textures are empty in the beginning. When bound with MediaPlayer, the OES texture will be updated during video playing, then we can use a FrameBuffer to draw the content of OES texture upon the 2D texture.

I've written a pure-Android version of this process and it works pretty well when I finally draw the 2D texture upon the screen. However, when I publish it as an Unity Android plugin and runs the same code on Unity, there won't be any pictures showing. Instead, it only displays a preset color from glClearColor, which means two things:

  1. The transferring process of OES texture -> FrameBuffer -> 2D texture is complete and Unity do receive the final 2D texture. Because the glClearColor is called only when we draw the content of OES texture to FrameBuffer.
  2. There are some mistakes during drawing happened after glClearColor, because we don't see the video frames pictures. In fact, I also call glReadPixels after drawing and before unbinding with the FrameBuffer, which is going to read data from the FrameBuffer we bound with. And it returns the single color's value that is same with the color we set in glClearColor.

In order to simplify the code I should provide here, I'm going to draw a triangle to a 2D texture through FrameBuffer. If we can figure out which part is wrong, we then can easily solve the similar problem to draw video frames.

The function will be called on Unity:

  public int displayTriangle() {     Texture2D texture = new Texture2D(UnityPlayer.currentActivity);     texture.init();      Triangle triangle = new Triangle(UnityPlayer.currentActivity);     triangle.init();      TextureTransfer textureTransfer = new TextureTransfer();     textureTransfer.tryToCreateFBO();      mTextureWidth = 960;     mTextureHeight = 960;     textureTransfer.tryToInitTempTexture2D(texture.getTextureID(), mTextureWidth, mTextureHeight);      textureTransfer.fboStart();     triangle.draw();     textureTransfer.fboEnd();      // Unity needs a native texture id to create its own Texture2D object     return texture.getTextureID();   } 

Initialization of 2D texture:

  protected void initTexture() {     int[] idContainer = new int[1];     GLES30.glGenTextures(1, idContainer, 0);     textureId = idContainer[0];     Log.i(TAG, "texture2D generated: " + textureId);     // texture.getTextureID() will return this textureId      bindTexture();      GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,         GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);     GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,         GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);     GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,         GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);     GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,         GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);      unbindTexture();   }    public void bindTexture() {     GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);   }    public void unbindTexture() {     GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);   } 

draw() of Triangle:

  public void draw() {     float[] vertexData = new float[] {         0.0f,  0.0f, 0.0f,         1.0f, -1.0f, 0.0f,         1.0f,  1.0f, 0.0f     };     vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)         .order(ByteOrder.nativeOrder())         .asFloatBuffer()         .put(vertexData);     vertexBuffer.position(0);      GLES30.glClearColor(0.0f, 0.0f, 0.9f, 1.0f);     GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);     GLES30.glUseProgram(mProgramId);      vertexBuffer.position(0);     GLES30.glEnableVertexAttribArray(aPosHandle);     GLES30.glVertexAttribPointer(         aPosHandle, 3, GLES30.GL_FLOAT, false, 12, vertexBuffer);      GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 3);   } 

vertex shader of Triangle:

attribute vec4 aPosition; void main() {   gl_Position = aPosition; } 

fragment shader of Triangle:

precision mediump float; void main() {   gl_FragColor = vec4(0.9, 0.0, 0.0, 1.0); } 

Key code of TextureTransfer:

  public void tryToInitTempTexture2D(int texture2DId, int textureWidth, int textureHeight) {     if (mTexture2DId != -1) {       return;     }      mTexture2DId = texture2DId;     GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTexture2DId);     Log.i(TAG, "glBindTexture " + mTexture2DId + " to init for FBO");      // make 2D texture empty     GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, textureWidth, textureHeight, 0,         GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);     Log.i(TAG, "glTexImage2D, textureWidth: " + textureWidth + ", textureHeight: " + textureHeight);      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);      fboStart();     GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0,         GLES30.GL_TEXTURE_2D, mTexture2DId, 0);     Log.i(TAG, "glFramebufferTexture2D");     int fboStatus = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);     Log.i(TAG, "fbo status: " + fboStatus);     if (fboStatus != GLES30.GL_FRAMEBUFFER_COMPLETE) {       throw new RuntimeException("framebuffer " + mFBOId + " incomplete!");     }     fboEnd();   }    public void fboStart() {     GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOId);   }    public void fboEnd() {     GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);   } 

And finally some code on Unity-side:

int textureId = plugin.Call<int>("displayTriangle"); Debug.Log("native textureId: " + textureId); Texture2D triangleTexture = Texture2D.CreateExternalTexture(   960, 960, TextureFormat.RGBA32, false, true, (IntPtr) textureId); triangleTexture.UpdateExternalTexture(triangleTexture.GetNativeTexturePtr()); rawImage.texture = triangleTexture; rawImage.color = Color.white; 

Well, code above will not display the expected triangle but only a blue background. I add glGetError after nearly every OpenGL functions call while no errors are thrown.

My Unity version is 2017.2.1. For Android build, I shut down the experimental multithread rendering and other settings are all default(no texture compression, not use development build, so on). My app's minimum API level is 5.0 Lollipop and target API level is 9.0 Pie.

I really need some help, thanks in advance!

0 Answers

Read More

Monday, June 4, 2018

How to update one Bezier curve as another is moved using a custom editor

Leave a Comment

I am creating Bézier curves using the code below which I got from here. I have also made a BezierPair game object which has two Bézier curves as child objects.

From the respective images below and BezierPair, where points[0]...points[3] is represented as P0...P3:

  1. I want P0 of each Bézier curve always remain the same when one is moved. In other words I want them to move together always, with the option of turning this movement off.

enter image description here

  1. Say P1 of both curves are apart. How can I make P1 of each curve move in the same direction covering the same distance?

enter image description here

  1. Say P2 of both curves are apart. How can I make P2 of one curve mirror P2 of another curve along a line joining P0 and P3? Note that the mirror line would be taken from the curve 1 in the example below because curve1's P2 is moved. If curve2's P2 is moved, then the mirror line will be taken from curve2's P0P3.

enter image description here

I don’t want to do this at run time. So a custom editor has to be used. I tried solving 1. in the code below but the position for the second curve wouldn’t update without my selecting BezierPair in the hierarchy window

Bezier:

public static class Bezier {  public static Vector3 GetPoint (Vector3 p0, Vector3 p1, Vector3 p2,   Vector3 p3, float t) { t = Mathf.Clamp01(t); float oneMinusT = 1f - t; return     oneMinusT * oneMinusT * oneMinusT * p0 +     3f * oneMinusT * oneMinusT * t * p1 +     3f * oneMinusT * t * t * p2 +     t * t * t * p3; }  public static Vector3 GetFirstDerivative (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) { t = Mathf.Clamp01(t); float oneMinusT = 1f - t; return     3f * oneMinusT * oneMinusT * (p1 - p0) +     6f * oneMinusT * t * (p2 - p1) +     3f * t * t * (p3 - p2); } } 

BezierCurve:

[RequireComponent(typeof(LineRenderer))] public class BezierCurve : MonoBehaviour {  public Vector3[] points; LineRenderer lr; public int numPoints = 49; bool controlPointsChanged = false;  bool isMoving = false;  public void Reset () { points = new Vector3[] {     new Vector3(1f, 0f, 0f),     new Vector3(2f, 0f, 0f),     new Vector3(3f, 0f, 0f),     new Vector3(4f, 0f, 0f) }; }  void Start()    {  lr = GetComponent<LineRenderer> (); lr.positionCount = 0; DrawBezierCurve ();  } public Vector3 GetPoint (float t) { return transform.TransformPoint(Bezier.GetPoint(points[0], points[1], points[2], points[3], t)); }  public void DrawBezierCurve ()  { lr = GetComponent<LineRenderer> (); lr.positionCount = 1; lr.SetPosition(0, points[0]);  for (int i = 1; i < numPoints+1; i++) {     float t = i / (float)numPoints;     lr.positionCount = i+1;     lr.SetPosition(i, GetPoint(t)); } }  public Vector3 GetVelocity (float t) { return transform.TransformPoint(     Bezier.GetFirstDerivative(points[0], points[1], points[2], points[3], t)) - transform.position; }  public Vector3 GetDirection (float t) { return GetVelocity(t).normalized; } } 

BezierCurveEditor:

[CustomEditor(typeof(BezierCurve))] public class BezierCurveEditor : Editor {  private BezierCurve curve; private Transform handleTransform; private Quaternion handleRotation;  private const int lineSteps = 10;  private const float directionScale = 0.5f;  private void OnSceneGUI () { curve = target as BezierCurve; handleTransform = curve.transform; handleRotation = Tools.pivotRotation == PivotRotation.Local ?     handleTransform.rotation : Quaternion.identity;  Vector3 p0 = ShowPoint(0); Vector3 p1 = ShowPoint(1); Vector3 p2 = ShowPoint(2); Vector3 p3 = ShowPoint(3);  Handles.color = Color.gray; Handles.DrawLine(p0, p1); Handles.DrawLine(p2, p3); Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f);  curve.DrawBezierCurve ();  if (GUI.changed) {     curve.DrawBezierCurve ();     EditorUtility.SetDirty( curve );     Repaint(); }  }   private void ShowDirections () { Handles.color = Color.green; Vector3 point = curve.GetPoint(0f); Handles.DrawLine(point, point + curve.GetDirection(0f) * directionScale); for (int i = 1; i <= lineSteps; i++) {     point = curve.GetPoint(i / (float)lineSteps);     Handles.DrawLine(point, point + curve.GetDirection(i / (float)lineSteps) * directionScale); } }  private Vector3 ShowPoint (int index) { Vector3 point = handleTransform.TransformPoint(curve.points[index]); EditorGUI.BeginChangeCheck(); point = Handles.DoPositionHandle(point, handleRotation); if (EditorGUI.EndChangeCheck()) {     Undo.RecordObject(curve, "Move Point");     EditorUtility.SetDirty(curve);     curve.points[index] = handleTransform.InverseTransformPoint(point); } return point; } } 

BezierPair:

public class BezierPair : MonoBehaviour {   public GameObject bez1; public GameObject bez2;  public void setupCurves()   {     bez1 = GameObject.Find("Bez1");     bez2 = GameObject.Find("Bez2"); } } 

BezierPairEditor:

[CustomEditor(typeof(BezierPair))] public class BezierPairEditor : Editor {  private BezierPair bezPair;   public override void OnInspectorGUI() {     bezPair = target as BezierPair;      if (bezPair.bez1.GetComponent<BezierCurve>().points[0] != bezPair.bez2.GetComponent<BezierCurve>().points[0])     {         Vector3 assignPoint0 = bezPair.bez1.GetComponent<BezierCurve>().points[0];         bezPair.bez2.GetComponent<BezierCurve>().points[0] = assignPoint0;      }      if (GUI.changed)     {          EditorUtility.SetDirty(bezPair.bez1);         EditorUtility.SetDirty(bezPair.bez2);         Repaint();     } } 

2 Answers

Answers 1

I tried solving 1. in the code below but the position for the second curve wouldn’t update without my selecting BezierPair in the hierarchy window

This is because you are using OnInspectorGUI() callback inside your BezierPairEditor class. It is only executed when the inspector of BezierPairEditor is shown on your editor window. Thus if you do not click on the GameObject with the BezierPair component, the BezierPair's inspector is not shown, and the callback does not trigger.

Instead, use the EditorApplication.update delegate. Inside your BezierPairEditor class:

void OnEnable() {     EditorApplication.update += OnUpdate; //Register to the update callback }  void OnUpdate() {     //Implement your code to update positions here } 

Secondly, try caching your BezierCurve references. This is because you don't really want to run GetComponent inside every update loop, as it is costly. Again, inside your BezierPairEditor class (I will omit the code above for clarity, merge it yourself):

BezierCurve bez1C; BezierCurve bez2C;  void OnEnable() {     BezierPair pair = target as BezierPair;     bez1C = pair.bez1.GetComponent<BezierCurve>();     bez2C = pair.bez2.GetComponenet<BezierCurve>(); }  void OnUpdate() {     //Do something with bez1C and bez2C here } 

Finally, to solve points 1 to 3, since you did not specify, I shall assume that you are moving bez1 manually, and bez2 should follow. In the case where either one can be moved manually and the other should follow, I would recommend you to implement an isChanged check in your BezierCurve class. Then in your BezierPairEditor class, you can check which one has moved, and update the other one accordingly.

Inside BezierPairEditor class (again, I will omit the code above for clarity, merge it yourself):

Vector2 bez1CPrev1;  void OnEnable() {     bez1CPrev1 = bez1C.points[1];      //Ensure that they have the same starting point     //Either you shift just points[0] of bez2 to be the same as bez1, or you shift every point. Implement this yourself. }  void OnUpdate() {     Vector2 disp = bez1C.points[1] - bez1CPrev1;      //1.      bez2C.points[0] = bez1C.points[0];      //2.     bez2C.points[1] = bez2C.points[1] + disp;      //3. Here, we are gonna use Vector2.Reflect(). Why?      //Imagine throwing a ball from newP2(curve1) to P3(curve1).     //If the 'surface' that the ball hits has a normal of P0(curve1)-P3(curve1), you will have the ball bounce back to reach newP2(curve2).     //Effectively: newP2(curve2) = P3(curve1) + [newP2(curve2) - P3(curve1)]. The term in the square brackets, we will do it with Vector2.Reflect().     bez2C.points[2] = bez1C.points[3] + Vector2.Reflect(bez1C.points[3] - bez1C.points[2], (bez1C.points[0] - bez1C.points[3]).normalized);      //Draw your bezier curve etc. here      bez1CPrev1 = bez1C.points[1]; } 

Answers 2

EDITED:

I dont think you'll need your BezierPair class. I suggest you to add a reference to the other BezierCurve object you want to "pair" as a public field on the BezierCurve class (paired). That other curve will get "paired" with this curve. Once paired, the constraints on the movement may apply. You can control the desired behaviors with the 3 public bool fields behavior1, behavior2 and behavior3.

Note#1: Instead of calling the method DrawBezierCurve from the Editor, I added the [ExecuteInEditMode] to the Component Class. This way, You don't mix responsibilities between the Component and the Editor: The BezierCurve component draws itself on the scene, while the BezierCurveEditor only manages edit logic, like applying the constraints and drawing the handlers.

BezierCurve:

using UnityEngine;  [RequireComponent(typeof(LineRenderer))] [ExecuteInEditMode] // Makes Update() being called often even in Edit Mode public class BezierCurve : MonoBehaviour {    public Vector3[] points;   public int numPoints = 50;   // Curve that is paired with this curve   public BezierCurve paired;   public bool behavior1; // check on editor if you desired behavior 1 ON/OFF   public bool behavior2; // check on editor if you desired behavior 2 ON/OFF   public bool behavior3; // check on editor if you desired behavior 3 ON/OFF   LineRenderer lr;    void Reset()   {     points = new Vector3[]     {       new Vector3(1f, 0f, 0f),       new Vector3(2f, 0f, 0f),       new Vector3(3f, 0f, 0f),       new Vector3(4f, 0f, 0f)     };   }    void Start()   {     lr = GetComponent<LineRenderer>();   }    void Update()   {     // This component is the only responsible for drawing itself.     DrawBezierCurve();   }    // This method is called whenever a field is changed on Editor   void OnValidate()   {     // This avoids pairing with itself     if (paired == this) paired = null;   }    void DrawBezierCurve()   {     lr.positionCount = numPoints;     for (int i = 0; i < numPoints; i++)     {       // This corrects the "strange" extra point you had with your script.       float t = i / (float)(numPoints - 1);       lr.SetPosition(i, GetPoint(t));     }   }    public Vector3 GetPoint(float t)   {     return transform.TransformPoint(Bezier.GetPoint(points[0], points[1], points[2], points[3], t));   }    public Vector3 GetVelocity(float t)   {     return transform.TransformPoint(Bezier.GetFirstDerivative(points[0], points[1], points[2], points[3], t)) - transform.position;   }    public Vector3 GetDirection(float t)   {     return GetVelocity(t).normalized;   } } 

Note#2: The desired behavior were coded inside the handler drawing methods, so you have access to Undo and other features.

Note#3: EditorUtility.SetDirty is considered obsolete since Unity 5.3 for marking objects as dirty for drawing, and should no-longer be used for modifying objects in scenes. Undo.RecordObject does the job.

BezierCurveEditor:

using UnityEngine; using UnityEditor;  [CustomEditor(typeof(BezierCurve))] // This attribute allows you to select multiple curves and manipulate them all as a whole on Scene or Inspector [CanEditMultipleObjects] public class BezierCurveEditor : Editor {   BezierCurve curve;   Transform handleTransform;   Quaternion handleRotation;   const int lineSteps = 10;   const float directionScale = 0.5f;    BezierCurve prevPartner; // Useful later.    void OnSceneGUI()   {     curve = target as BezierCurve;     if (curve == null) return;     handleTransform = curve.transform;     handleRotation = Tools.pivotRotation == PivotRotation.Local ? handleTransform.rotation : Quaternion.identity;      Vector3 p0 = ShowPoint(0);     Vector3 p1 = ShowPoint(1);     Vector3 p2 = ShowPoint(2);     Vector3 p3 = ShowPoint(3);      Handles.color = Color.gray;     Handles.DrawLine(p0, p1);     Handles.DrawLine(p2, p3);     Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f);      // Handles multiple selection     var sel = Selection.GetFiltered(typeof(BezierCurve), SelectionMode.Editable);     if (sel.Length == 1)     {       // This snippet checks if you just attached or dettached another curve,       // so it updates the attached member in the other curve too automatically       if (prevPartner != curve.paired)       {         if (prevPartner != null) { prevPartner.paired = null; }         prevPartner = curve.paired;       }     }      if (curve.paired != null & curve.paired != curve)     {       // Pair the curves.       var partner = curve.paired;       partner.paired = curve;       partner.behavior1 = curve.behavior1;       partner.behavior2 = curve.behavior2;       partner.behavior3 = curve.behavior3;     }   }    void ShowDirections()   {     Handles.color = Color.green;     Vector3 point = curve.GetPoint(0f);     Handles.DrawLine(point, point + curve.GetDirection(0f) * directionScale);     for (int i = 1; i <= lineSteps; i++)     {       point = curve.GetPoint(i / (float)lineSteps);       Handles.DrawLine(point, point + curve.GetDirection(i / (float)lineSteps) * directionScale);     }   }    // Constraints for a curve attached to back   // The trick here is making the object being inspected the "master" and the attached object is adjusted to it.   // This way, you avoid the conflict of one object trying to move the other.   // [ExecuteInEditMode] on component class makes it posible to have real-time drawing while editing.   // If you were calling DrawBezierCurve from here, you would only see updates on the other curve when you select it   Vector3 ShowPoint(int index)   {     Vector3 point = handleTransform.TransformPoint(curve.points[index]);     EditorGUI.BeginChangeCheck();     point = Handles.DoPositionHandle(point, handleRotation);     if (EditorGUI.EndChangeCheck())     {       Undo.RecordObject(curve, "Move Point" + index.ToString());       var thisPts = curve.points;       var pairPts = curve.paired.points;       switch (index)       {         case 0:           {             if (curve.behavior1)             {               pairPts[0] = curve.paired.transform.InverseTransformPoint(point);             }             break;           }         case 1:           {             if (curve.behavior2)             {               pairPts[1] += thisPts[1] - handleTransform.InverseTransformPoint(point);             }             break;           }         case 2:           {             if (curve.behavior1)             {               pairPts[2] = thisPts[3] + Vector3.Reflect(thisPts[3] - thisPts[2], (thisPts[0] - thisPts[3]).normalized);             }             break;           }         default:           break;       }       curve.points[index] = handleTransform.InverseTransformPoint(point);     }     return point;   } } 

For have it working, reference one BezierCurve to another's paired field through inspector, and set ON/OFF the behaviors you want.

Tips: tinker the properties of the LineRenderer to get cool gradients or width variation (like a brush stroke). If you have a cusp node and want it to look continuous, increase the value of End Cap Vertices on the Line Renderer. Use Sprites-Default as Material, for 2D.

Read More

Thursday, May 10, 2018

How to align “tracks” or modular objects in Unity ?

Leave a Comment

I'm developing a simple game, where user can place different but modular objects (for instance: tracks, road etc).

My question is: how to match and place different object when placed one near the other ?

My first approach is to create an hidden child object (a box) for each module objects, and put it in the border where is possible to place other object (see my image example), so i can use that coordinates (x,y,z) to align other object.

But i don't know if the best approach.

enter image description here

enter image description here

Thanks

2 Answers

Answers 1

Summary:

1.Define what is a "snapping point"

2.Define which is your threshold

3.Update new game object position

Little Explanation

1. So I suppose that you need a way to define which parts of the object are the "snapping points". Cause they can be clear in some examples, like a Cube, where the whole vertex could be snapping points, but it's hard to define that every vertex in amorphous objects.

A simple solution could be the one exposed by @PierreBaret, whic consists in define on your transform component which are the "snapping points". The other one is the one you propouse, creating empty game objects that will act as snapping points locations on the game object.

2.After having those snaped points, when you will drop your new gameObject, you need to define a threshold, as long as you don't want that every object snaps allways to the nearest game object.

3.So you define a minimum distance between snapping points, so if your snapping point is under that threshold, you will need to update it's position, to adjust to the the snapped point.

Visual Representation:

enter image description here

Note: The Threshold distance is showing just ONE of the 4 current threshold checks on the 4 vertex in the square, but this dark blue circle should be repilcate 3 more times, one for each green snapping point of the red square

Of course this method seems expensive, you can make some improvements like setting a first threshold between gameobjects, and if the gameObject is inside this threshold, then check snapping threshold distance.

Hope it helps!

Answers 2

Approach for arbitrary objects/models and deformable models.

[A] A physical approach would consider all the surfaces of the 2 objects, and you might need to check that objects don't overlap, using dot products between surfaces. That's a bit more expensive computing, but nothing nasty. If there is no match involved here, you'll be able to add matching features (see [B]). However, that's the only way to work with non predefined models or deformable models.

Approaches for matching simple and complex models

[B] Snapping points are a good thing but it's not sufficient alone. I think you need to make an object have:

  • a sparse representation (eg., complex oriented sphere to a cube),
  • and place key snapping points,
  • tagged by polarity or color, and eventually orientation (that's oriented snapping points); eg., in the case of rails, you'll want rails to snap {+} with {+} and forbid {+} with {-}. In the case of a more complex object, or when you have several orientations (eg., 2 faces of a surface, but only one is candidate for an pair of objects matching) you'll need more than 2 polarities, but 3 different ones per matching candidate surface or feature therefore the colors (or any enumeration). You need 3 different colors to make sure there is a unique 3D space configuration. You create something that is called in chemistry an enantiomer.
  • You can also use point pair features that describes the relative position and orientation of two oriented points, when an oriented surface is not appropriate.

References

Some are computer vision papers or book extracts, but they expose algorithms and concepts to achieve what I developed in my answer.

  1. Model Globally, Match Locally: Efficient and Robust 3D Object Recognition, Drost et al.

  2. 3D Models and Matching

Read More

Wednesday, May 2, 2018

Embedded Unity in Android crashes app

Leave a Comment

I have an embedded Unity3d project in my android program. The 3d project opens fine in stereo view to be used in a DayDream headset (although it always says controller disconnected which is a separate issue). When I click the x to exit the VR view, it goes back to the android application as expected but after 1 second the app flips to landscape and crashes.

Below is the part of the stacktrace where I think the error is occurring but I definitely could be wrong. Any help would be welcome. Thanks

04-16 10:11:17.382 1931-9239/? W/IcingConfig: Invalid input from icing corpus JSON flag.     android.util.MalformedJsonException: Expected ':' at line 60 column 9         at android.util.JsonReader.syntaxError(JsonReader.java:1159)         at android.util.JsonReader.objectValue(JsonReader.java:687)         at android.util.JsonReader.peek(JsonReader.java:347)         at android.util.JsonReader.hasNext(JsonReader.java:319)         at android.util.JsonReader.skipValue(JsonReader.java:549)         at com.google.android.apps.gsa.staticplugins.searchboxroot.features.n.a.k.sA(SourceFile:37)         at com.google.android.apps.gsa.staticplugins.searchboxroot.features.n.a.k.<init>(SourceFile:11)         at com.google.android.apps.gsa.staticplugins.searchboxroot.bf.c(SourceFile:101)         at com.google.android.apps.gsa.staticplugins.searchboxroot.bf.a(SourceFile:60)         at com.google.android.apps.gsa.staticplugins.searchboxroot.bq.<init>(SourceFile:35)         at com.google.android.apps.gsa.staticplugins.searchboxroot.cb.get(SourceFile:54)         at dagger.internal.DoubleCheck.get(SourceFile:10)         at com.google.android.apps.gsa.staticplugins.searchboxroot.a.cmZ(SourceFile:323)         at com.google.android.apps.gsa.staticplugins.searchboxroot.a.b.get(SourceFile:14)         at com.google.android.apps.gsa.search.core.service.worker.a.g.call(Unknown Source:4)         at com.google.android.libraries.gsa.runner.a.a.d(SourceFile:27)         at com.google.android.libraries.gsa.runner.a.d.call(Unknown Source:4)         at java.util.concurrent.FutureTask.run(FutureTask.java:266)         at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)         at java.util.concurrent.FutureTask.run(FutureTask.java:266)         at com.google.android.apps.gsa.shared.util.concurrent.b.f.run(Unknown Source:4)         at com.google.android.apps.gsa.shared.util.concurrent.b.at.run(SourceFile:4)         at com.google.android.apps.gsa.shared.util.concurrent.b.at.run(SourceFile:4)         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)         at java.lang.Thread.run(Thread.java:764)         at com.google.android.apps.gsa.shared.util.concurrent.b.h.run(SourceFile:6) 

app homescreen unity opening in stereo modeunity 3d project openapp crashing

My code is attached below MAIN ACTIVITY

public class MainActivity extends AppCompatActivity {      Button unityVRButton;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          unityVRButton = (Button)findViewById(R.id.open_unity);         unityVRButton.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 startActivity(new Intent(MainActivity.this,GameActivity.class));             }         });     } } 

ACTIVITY THAT CALLS UNITY

import android.os.Bundle;  import com.rbw.TestVR.UnityPlayerActivity;  /**  * Created by kshah on 3/15/2018.  */  public class GameActivity extends UnityPlayerActivity {     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);     } } 

Entire project can be found at this link

https://drive.google.com/drive/folders/1jFp4pZBMgevB6Z2YgFinYNg6d4KPQJDb?usp=sharing

1 Answers

Answers 1

There may be a couple different issues. One is the malformed json in the stack trace.

However crashes on screen rotation are usually something else.

It would seem that there is some task that is finishing with references to your old view. When the app is switched to landscape the activity is destroyed and recreated and all your views are recreated. If a long running process is carrying a reference to the view that was garbage collected, your app will crash.

A quick way to tell if this is actually the issue is to add this to your manifest under the calling activity. This will force the calling activity to remain in a portrait mode. If the app does not crash after exit, then its likely that there is a process that is holding reference to destroyed views.

  <activity android:name=".MyActivity" android:label="@string/title_my_activity" android:screenOrientation="portrait" /> 

Here is more info: http://code.hootsuite.com/orientation-changes-on-android/

Read More

Friday, April 20, 2018

Have 3d text shader be non-emissive?

Leave a Comment

In Unity, how can I stop my 3d texts from "glowing" in the dark?

I'm using below shader code, for instance, but the texts turn up much brighter/ self-emissive than other things. Changing to "Lighting On" gets rid of the glow, but will then also get rid of the material color, and turn up black.

How to solve this? Many thanks!

Shader "GUI/3D Text Shader - Cull Back" { Properties {     _MainTex ("Font Texture", 2D) = "white" {}     _Color ("Text Color", Color) = (1,1,1,1) }  SubShader {     Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }     Lighting Off Cull Back ZWrite Off Fog { Mode Off }     Blend SrcAlpha OneMinusSrcAlpha     Pass {         Color [_Color]         SetTexture [_MainTex] {             combine primary, texture * primary         }     } } 

1 Answers

Answers 1

Copied from comments, added for context:

I suspect the emissive glow is just the material's unlit color contrasting against a dark/variably lit scene? A lit shader could fix such an issue, however Unity's TextMesh component appears to not generate mesh normals and thus the shader's lighting calculations will corrupt (if at all be compiled). It explains why Lighting On outputs black. Without access to TextMesh internals and confined to the limitations of fixed-function shaders, a custom shader may be your only option.

The following is a basic Surface Shader using the Lambert lightning model. Under the hood it will compile to a standard vertex/fragment shader with Unity's lighting calculations automagically injected. It's been written as a drop-in replacement, so simply add it to your project and drag and drop it onto your material:

Shader "GUI/3D Text Shader - Lit" {     Properties     {         _Color ("Text Color", Color) = (1,1,1,1)         _MainTex ("Font Texture", 2D) = "white" {}     }      SubShader     {         Tags {"RenderType"="Transparent" "Queue"="Transparent"}         Cull Back          CGPROGRAM            #pragma surface SS_Main Lambert vertex:VS_Main alpha:blend          #pragma target 3.0          uniform fixed4 _Color;         uniform sampler2D _MainTex;          struct Output         {              float4 vertex    : POSITION;              float3 normal    : NORMAL;                   float4 texcoord  : TEXCOORD0;              float4 texcoord1 : TEXCOORD1;              float4 texcoord2 : TEXCOORD2;         };          struct Input         {             float2 uv_MainTex;         };                void VS_Main (inout Output o)          {                       // Generate normals for lighting.             o.normal = float3(0, 0, -1);         }          void SS_Main (Input IN, inout SurfaceOutput o)         {                    fixed4 c = tex2D (_MainTex, IN.uv_MainTex);             o.Albedo = _Color.rgb;             o.Alpha = c.a;         }         ENDCG     } } 
Read More

Tuesday, March 27, 2018

How to Configure Heroku to host files using gzip compression

Leave a Comment

I am trying to deploy a node.js app on heroku , which is serving unity webGL exported game to clients. After Unity3d 5+ release , WebGL exports by Unity uses gzip compression by default .

Well ,

heroku server [Node.js] dont serves gzip compressed files , which is causing my Game to throw error in console on load , main unity loading window wont update (just blank) till files dont get completely download & a slight delay while browser manually decompresses it.

enter image description hereThese are the file types Unity WebGL Export provides = || . datagz || . jsgz || . memgz ||

So what i need is , a way to configure heroku node.js server for serving the gzip compression .

1 Answers

Answers 1

It doesn't look like you are having issues serving gzipped files. The messages in the console could be a separate issue altogether.

What is more likely is that your node app is not serving the right folder or files. If you can provide a list of files that is in your build folder (I assume that this is where Unity places its files), I can take a look.

Also, do review your Heroku configuration, namely the command used by the web process. If it is npm start or something, then look at the script it points to (see in your package.json file), and see if it is serving files out of the build folder.

Read More

Wednesday, March 14, 2018

Unity: How to move a player using Character controller in step?

Leave a Comment

I would like to move my Player in "block" of 0.1 unity unit (or 1).

How to modify / configure Character controller to move with "fixed" step?

2 Answers

Answers 1

You can use transform.Translate to move the character

    //moves the character 1 unit in x direction     transform.Translate(1.0f, 0.0f, 0.0f); 

Answers 2

If you want to use the Character Controller component to move your object, you would want to use its dedicated methods:

  1. Move
  2. SimpleMove

Also, there's some difference between the 2 methods stated above.
The Move method is more complex and performance wise. As it takes care of complex physics such as gravity, collisions and will move the object by motion.
The SimpleMove method, instead, is more lightweight because it will only move the object without taking care of environmental physics.

If you want to move by a single unit, probably the code should look something like this:

//Controller being your character controller component Controller.SimpleMove(Vector3.forward); 
Read More

Tuesday, March 13, 2018

Remove the white and black screen when starting the Android application made with Unity

Leave a Comment

Unity:2017.2.1f1
Device:ASUS_Z017DA(Android 8.0.0)

We want to shorten the Android application launch time.
We upgraded to Unity Plus for that.

We have confirmed the operation with minimum application.
We just created a new project, changed package name and hidden splash screen.

  • Player Settings - Other Settings - Identification - Package Name(Modify)
  • Player Settings - Splash Image - Splash Screen - Show Splash Screen(Uncheck)

However, when you start Android application, screen of 3 kinds of colors is displayed on the screen.

Movie

  • White -> Black -> Blue(314D7900)

The last Blue (314D7900) screen is the default scene. It is the background color of the main camera. We do not regard it as a problem.

We do not like the screen of White and Black. We feel these are not beautiful. Is it possible to remove them?

If we can not erase them,Is it possible to shorten these display times?
If we can not shorten those display times,Is it possible to change those colors?

As we further advance the implementation, these display times will be even longer.
We tried various settings and created a loading scene.
But We could not improve them.

Even though we saw other released applications, it did not look like this.
Did we do something wrong?

We tried these. We checked and unchecked the Splash Screen. We checked and unchecked the Unity Logo. We tried to create a loading scene.

But they only slowed the startup speed. We just want to know how to start simple and fast.

2 Answers

Answers 1

White -> Black -> Blue(314D7900) is caused by your theme and activity's layout background.

In your app's manifest file, check your activity's or application's android:theme attribute, such as android:theme="@style/AppTheme"

Then open the AppTheme style, add a windowBackground or android:windowBackground set the color to Blue:

  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">     <item name="colorPrimary">@color/colorPrimary</item>     <item name="colorPrimaryDark">@color/colorPrimaryDark</item>     <item name="colorAccent">@color/colorAccent</item>     <item name="windowBackground">@color/blue</item>   </style> 

Then in your main activity's layout file, I think you set a black background color, now remove the background.

Now start you app, you will see just the Blue background.

Because you not post your code, that's my best guess. If not solve your problem, please share your project in Github, I can check where is going wrong.

Answers 2

Please add this property in you style, i have used this and it seems to work for me:

<?xml version="1.0" encoding="utf-8"?> <resources>    <style name="AppTheme" parent="android:Theme">         <item name="android:windowDisablePreview">true</item>   </style> </resources> 

Thank you.

Read More

Tuesday, January 16, 2018

Display a python output with special characters in GUI label unity

Leave a Comment

Am running a python script from unity, and I want the output to be displayed in a GUI label in unity, the output contain special characters like é,ç,... but am getting symbols instead. This is what I tried so far but no luck

using (Process proc = Process.Start (start)) {             using (StreamReader reader = proc.StandardOutput) {                 string result = reader.ReadToEnd ();                 UTF8Encoding utf8 = new UTF8Encoding ();                 byte[] encodedBytes = utf8.GetBytes (result);                 UnityEngine.Debug.Log (result);                 Message1.text = result;              }         } 

result is the output: it should be

('fromaje', 'Fausse:') ('Correction suggérér:','fromage') 

But am getting:

enter image description here

1 Answers

Answers 1

When you create your process use:

    var proc = new Process {     StartInfo = new ProcessStartInfo {         FileName = "python.exe whatever.py",         Arguments = "yourargs",         UseShellExecute = false,         RedirectStandardOutput = true,         CreateNoWindow = true     }  }; 

Then read the string by doing this:

proc.Start(); StringBuilder bldr = new StringBuilder(); while (!proc.StandardOutput.EndOfStream) {     bldr.append(proc.StandardOutput.ReadLine()+"\n"); } 

You can get the full output by doing:

bldr.ToString() 
Read More

Tuesday, October 10, 2017

SerializationException: Could not find type 'System.Collections.Generic.List`1 in c# unity3d

Leave a Comment

I am trying to serialize and deserialize an object in c# unity3d. For that I am using the below code. But I am getting an error mentioned below.

Error: SerializationException: Could not find type 'System.Collections.Generic.List`1[[ABC, Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null]]'.

This is not happening while I serialize the object save to file and load it from file while I am playing the game with out stopping the game.

But the error occurs if I stop the game and change any line of code ( irrelevant to serialization and Deserialization )and load data from file saved previously and trying to deserialize I am getting an SerializationException.

I am using visual studio editor and unity3d version is 5.5.4

I may be missing something very simple thing. could someone help me in resolving this.

Thanks.

public static string SerializeObject<T>(T objectToSerialize) {     BinaryFormatter bf = new BinaryFormatter();     MemoryStream memStr = new MemoryStream();      try     {         bf.Serialize(memStr, objectToSerialize);         memStr.Position = 0;          return Convert.ToBase64String(memStr.ToArray());     }     finally     {         memStr.Close();     } }  public static T DeserializeObject<T>(string str) {     BinaryFormatter bf = new BinaryFormatter();     bf.Binder = new CurrentAssemblyDeserializationBinder();     byte[] b = Convert.FromBase64String(str);     MemoryStream ms = new MemoryStream(b);      try     {         return (T)bf.Deserialize(ms);     }     finally     {         ms.Close();     } } 

Class I am using:

    [Serializable]    public class ABC : ISerializable   {     public SerializableDictionary<int, ExampleClass> a = new SerializableDictionary<int, ExampleClass>();      public GameObject b;     public GameObject c;     public bool d = false;     public ABC e;     public int f;     public string g = "";     public int h = -1;     public int i = -1;     public int j = -1;     public string k = "default";     public XYZ l = XYZ.P;   }      [Serializable]     public enum XYZ     {         P,         Q     }       [Serializable()]     public class ABCListWrapper : ISerializable     {      public List<ABC> abcMappings = new List<ABC>();     public string version = "1.53";     public float interval;     }       //Serilization      abcLW = new ABCListWrapper();     abcW = getABCListWObj();     string abcWString = SerializeObject(abcW);     File.WriteAllText(Application.streamingAssetsPath + "/filename.json", abcWString);       //Deserilization call      ABCListWrapper l = new ABCListWrapper();     string l_1 = File.ReadAllText(Application.streamingAssetsPath + "/filename.json");     l =  DeserializeObject<ABCListWrapper>(l_1); 

Attempt to resolve the issue:

public sealed class CurrentAssemblyDeserializationBinder : SerializationBinder {     public override Type BindToType(string assemblyName, string typeName)     {         Version assemVer1 = Assembly.GetExecutingAssembly().GetName().Version;         Debug.Log("ASSEM VER: " + assemVer1 + "--NAME--" + assemblyName + " --OVERAL-- " + Assembly.GetExecutingAssembly().FullName + " --TYPE-- " + typeName );         //assemblyName = Assembly.GetExecutingAssembly().FullName.Replace(assemVer1.ToString(), "1.0.2.23455");         //string assemblyNameCustom = "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null";          bool isList = false;          if (typeName.Contains("List`1"))             isList = true;         // other generics need to go here          if (isList)             return Type.GetType(string.Format("System.Collections.Generic.List`1[[{0}, {1}]]", "ABC", "Assembly-CSharp, Version=1.0.2.18931, Culture=neutral, PublicKeyToken=null"));         else             return Type.GetType(string.Format("{0}, {1}", assemblyName, typeName));      }  } 

But I am getting the same exception and the log in BindToType is never printed. So it means the function BindToType in the SerilizationBinder.

2 Answers

Answers 1

The binary formatter is storing the assembly version information along with the serialized type. So even when the type is not changed, the serialization/deserialization changes as soon as the assembly is updated.

See this related Q/A for details: Binary Deserialization with different assembly version and the relevant MSDN article.

Normally I would close-vote this as a duplicate, but I can't because of the open bounty, so I decided to answer instead ;)

Answers 2

For fast binary serialization Protocol Buffers can be good option. Also it should resolve compatibility issues (you can control fields order/exclusion manually)

Read More

Saturday, July 22, 2017

optimization - stepping may behave oddly : iOS/Unity

Leave a Comment

I am trying to integrate unity to iOS application. I have followed this tutorial http://www.agnosticdev.com/blog-entry/swift/integrating-unity-and-vuforia-ios-swift-project

Now after integrating when i start my app it crashes and show this error on console : was compiled with optimization - stepping may behave oddly; variables may not be available.

Crash : Crash log

I have tried googling this and found these links :

  1. APPNAME was compiled with optimization - stepping may behave oddly; variables may not be available
  2. 'Project Name' was compiled with optimization - stepping may behave oddly; variables may not be available
  3. Xcode target compiled with optimization
  4. Xcode: Cannot set optimization level for debug

and nothing changed.

I have changed optimization level of both project and pod. I have also added this line to pod file : project 'MyProject', 'Debug - local'=>:debug, 'Debug - staging'=>:debug, 'Debug - PRODUCTION'=>:debug ( before target 'projectname' do)

Also I have unchecked Strip Engine Code in unity.

What can i do to overcome this error ? Any help would be appreciated, thanks.

0 Answers

Read More

Wednesday, July 19, 2017

Is there a standard/recommended directory structure for Unity projects?

Leave a Comment

My next project will use Unity 5.6. It will be a game and that will leverage AssetBundle for remote scenes loading. New scenes will be incrementally added afterward. Therefore I hope I won't use a too bad structure that need to be changed a lot in the later stage of the project. Is there a standard/recommended directory structure for Unity projects?

2 Answers

Answers 1

Unity actually does encourage the following structure:

Assets > Animations > > ... > Editor > > ... > Models > > ... > Prefabs > > ... > Scripts > > ... > Textures > > ... 

This is due to the object oriented way in which Unity thinks: Each folder contains only the information of a certain type needed for an asset. This is especially visible when you look at the Special Folders in Unity.

Even when you look at they build up their standard assets you will notice this structure. I hope you won't have a lot of scenes which do not share any assets with the other scenes, because this would be a very big waste of resources.

What is notable in the Standard Assets, is that in their demo, they have a folder called Menu which contains its own Scripts, Prefabs and Sprites folders.

So I suggest you do the following (note: This is my opinion):

  • Try to separate everything into their own folders without grouping into assets but into filetypes
  • In some cases where scenes have their own assets that are never shared, you may group them into a separate folder
  • I really do not like the idea of "static assets" and "dynamic assets" in the folder structure as proposed by the blogentry of link1 ryemoss gave you. Dynamically loaded assets require you to use the Resources folder anyway, so use this folder instead and put your grouping folders ("Bundle1", "Bundle2", etc.) inside it.
  • Never mix your system. If you think something isn't fitting, change it. But change it for the whole project. Be consistent.
  • Do not force folders to be moved up or down by adding an underscore or something equivalent as prefix.
  • Document your structure somewhere. Depending how large your project is, it may help. But folderstructures are like code, if they don't need a comment to describe what's happening, its (mostly) best.

Answers 2

At the end of the day, it comes down to whatever works the best for you and makes the most sense for the project. Working on small solo projects, I've found that keeping a simple folder structure separating asset types has worked well to keep things organized (Textures, Scripts, Prefabs, Sprites, etc). Another popular method is to organize by object type:

Animals
..Snake
....sprite
....script
..Crow
....sprite
....script

In my experience, organizing by Scene has generally not ended up working out well, especially in the case where assets are shared between scenes - stuff tends to get lost.

I suggest taking some time to mess around with your organization and see what feels right for you, especially if this is your first unity project. Moving files around after you start will not break associations in the inspector, assuming you are not searching through directories in your scripts.

If you need more help deciding, take a look at some of the links below. Link 3 in particular has a pretty lengthy discussion on this topic.

Read More

Sunday, June 4, 2017

MongoDB not querying

Leave a Comment

Hi I am trying to query my Mongo Database by using a list of Facebook ID's as the parameter in order to return the list of users with corresponding accounts. The method works fine in the Unity Editor however when I run it on iOS I get a constructor error (I have set a blank default constructor in order to solve the issue however it still doesn't work)

Initial Method

 public void FetchData()     {         //data = Mongo.Instance.players.FindAll().ToList();         if (FB.IsLoggedIn)         {             FB.API("me/friends", HttpMethod.GET, FriendsHighscoreHndlr);         }     } 

Callback Method

public void FriendsHighscoreHndlr (IGraphResult FBresult){                         var dict = Json.Deserialize(FBresult.ToString()) as Dictionary<string,object>;             var friendList = new List<object>();             friendList = (List<object>)(dict["data"]);              int _friendCount = friendList.Count;             Debug.Log("Found friends on FB, _friendCount ... " +_friendCount);             List<string> friendIDsFromFB = new List<string>();             for (int i=0; i<_friendCount; i++) {                 string friendFBID = getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "id");                 string friendName =    getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "name");                 Debug.Log( i +"/" +_friendCount +" " +friendFBID +" " +friendName);                 friendIDsFromFB.Add(friendFBID);             }             //friendIDsFromFB.Add(AccessToken.CurrentAccessToken.UserId);             var query = Query.In("facebookID", BsonArray.Create(friendIDsFromFB));             //Debug.Log(query);             data = Mongo.Instance.players.Find(query).ToList();         } 

Data Value for Key Method

private string getDataValueForKey(Dictionary<string, object> dict, string key) {             object objectForKey;             if (dict.TryGetValue(key, out objectForKey)) {                 return (string)objectForKey;             } else {                 return "";             }         } 

Return Query Result

{     "_id" : ObjectId("XXXXXX"),     "facebookID" : "XXXXXXXXXXXXXX",     "name" : "John Doe",     "highScore" : 40501 } 

1 Answers

Answers 1

Have you tried using a filter from Mongo's .NET drivers?

I would suggest trying something like the example below. (Note: this event is being fired on a pre-defined object which is being defined as a collection.)

        var filter = Builders<Object>.Filter.Eq(obj => obj.attribute, List<IDs>); 
Read More

Monday, May 1, 2017

Handling authentication in Nodejs with passport-facebook-token, request coming from frontend Facebook SDK

Leave a Comment

I am working on a Unity App. For login, there are two methods, one using Email and another using Facebook. In case of login separately, I do not have any problem. Registration and Login with Email works perfectly. And Login with Facebook works perfectly as well. Here's the workflow, I created just to make you clear. Login work flow

tl;dr [read update]

There's another schema for account, which is used for login.

var Account = new Schema({   email: String,   password: String,   facebookId: String }); 

Things to know about the backend API.

  1. Passport is used for Authentication
  2. Successful login returns email and token to the client through API.
  3. On client, token is most to play game and use the overall features.

As I said, I have already covered the part when if a client registers and login using email, then client can use the app. But my confusion is handling the logins with Facebook. Facebook SDK is already integrated with the Unity App, and Login is success.

Now, how can I use the Facebook login information that is generated by the Facebook SDK onto my back end, so that I can authorize the user throughout the system, as done in email login.

Going through other questions in SO and Google, I came across passport-facebook-token, I also tried using the plugin but could not came up with the logic and flow for handling the data from SDK into the Nodejs API. Can someone me help understand how it is done?

Update 1: Using passport-facebook-token

Strategy on index.js

passport.use(new FacebookTokenStrategy({     clientID: FACEBOOK_APP_ID,     clientSecret: FACEBOOK_APP_SECRET   }, function(accessToken, refreshToken, profile, done) {     Account.findOrCreate({facebookId: profile.id}, function (error, user) {       return done(error, user);     });   } )); 

Controller API

api.post('/auth/facebook/token', passport.authenticate('facebook-token'), function (req, res) {   console.log(req.user);   // do something with req.user   res.sendStatus(req.user? 200 : 401); } ); 

Now, there is no error shown, but the data is not inserted into Account Schema, I have this findOrCreate() function in Model.

Account.statics.findOrCreate = function findOrCreate(profile, cb){ var userObj = new this(); this.findOne({facebookId : profile.id},function(err,result){     if(!result){         userObj.facebookId = profile.id;         //....         userObj.save(cb);     }else{         cb(err,result);     } }); }; 

1 Answers

Answers 1

you can use facebook-passport for that, you can check the documentation here: https://github.com/jaredhanson/passport-facebook but basically, after you have already set up your developer account and got your keys from the developer site of facebook you can implement a FacebookStrategy object like following where you have to specify your credential and also a callback that in the documentation example is an http request to another resource of an express server where you can then save the data to mongo

passport.use(new FacebookStrategy({     clientID: FACEBOOK_APP_ID,     clientSecret: FACEBOOK_APP_SECRET,     callbackURL: "http://localhost:3000/auth/facebook/callback" }, function(accessToken, refreshToken, profile, cb) {     User.findOrCreate({ facebookId: profile.id }, function (err, user) {     return cb(err, user);    });  }  )); 
Read More

Wednesday, April 19, 2017

Android Plugin UnitySendMessage Never Called

Leave a Comment

This was working a few weeks ago, but now I've noticed my OnReward message is no longer called from my custom plugin.

In my rewardcenter.cs class I call the plugin class to set the listener to the gameObject that this script is attached to (in this example case it's GameObject):

public class rewardcenter : MonoBehaviour {     int counter = 0;     void Start () {          OnReward("85");     }      // Update is called once per frame     void Update ()     {         if (counter == 20) {             #if UNITY_ANDROID                  PluginClass.SetRewardListener(gameObject.name);                 Debug.Log("Adding Android Reward Listener: " + gameObject.name);             #endif         }          counter++;     }      void OnReward(string quantity)     {         Debug.Log("OnReward: " + quantity);     } } 

In the PluginClass.cs file you can see how I call the setUnityObjectName call on the java plugin class to set the unity object to the passed in GameObject's name string GameObject:

private static AndroidJavaObject pluginClassInstance = null; private static AndroidJavaObject activityContext = null;  // pass in the GameObject that implements the OnReward method public static void SetRewardListener(string gameObjName) {     if (activityContext == null) {         using (AndroidJavaClass activityClass = new AndroidJavaClass ("com.unity3d.player.UnityPlayer")) {             activityContext = activityClass.GetStatic<AndroidJavaObject> ("currentActivity");         }     }      using (AndroidJavaClass pluginClass = new AndroidJavaClass ("pluginclass.com.PluginClass")) {         if (pluginClass != null) {             pluginClassInstance = pluginClass.CallStatic<AndroidJavaObject> ("getInstance");             activityContext.Call ("runOnUiThread", new AndroidJavaRunnable (() => {                 pluginClassInstance.Call("setUnityObjectName", gameObjName);             }));         }     } } 

In the java PluginClass itself later on we attempt to call OnReward using UnitySendMessage on our game object:

   public void unityEarnedReward(String quantity) {         Log.d(TAG, "unityEarnedReward: " + quantity);         if (PluginClass.getInstance()._unityObjectName != null) {             Log.d(TAG, "calling OnReward(" + quantity + ") on unityObject with name: " + PluginClass.getInstance()._unityObjectName);             com.unity3d.player.UnityPlayer.UnitySendMessage(PluginClass.getInstance()._unityObjectName, "OnReward", quantity);         }     } 

I end up with a log output in Android Studio of:

calling OnReward(202) on unityObject with name: GameObject 

But it never seems to actually call OnReward within the game.

Just for kicks I tried calling OnReward when the script starts, it ends up with an output of:

OnReward: 85 

So I know it works and prints to the console when it is executed.

Any idea where I'm going wrong? The weird thing is this worked a few weeks ago, but now the OnReward method isn't executed.

EDIT:

I also tried running it without the specific class declaration like this with no luck:

UnityPlayer.UnitySendMessage(PluginClass.getInstance()._unityObjectName, "OnReward", quantity); 

I also renamed my gameObject to be MyCustomPlugin but while the android code triggered it doesn't seem the OnReward method was ever triggered on the script linked to MyCustomPlugin.

Screenshot of script: enter image description here

When I run this code:

void Update ()     {         var unityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");         unityPlayer.CallStatic ("UnitySendMessage", gameObject.name, "OnReward", "185");          OnReward ("86");      } 

I end up with two Log messages:

04-14 10:47:47.085 10341-10354/? I/Unity: OnReward: 86                                            (Filename: ./artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51) 04-14 10:47:47.095 10341-10354/? I/Unity: OnReward: 185                                            (Filename: ./artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51) 

0 Answers

Read More

Wednesday, March 8, 2017

Google Cloud Platform with Unity

Leave a Comment

I was thinking of Google Cloud Platform (GCP) as the backend for Unity.

Can someone guide me to develop the GCP flow as authoritative, like if a request comes for deducting X gems to convert into the amount, then GCP get gems conversion rate from metadata, calculates the amount and increments amount in the user gamestate, also returns the new total balance as a callback [Remember: metadata/gamestate is saved in MongoDB (JSON)]

As i worked with AWS servers, so i want to know how to do it in GCP.

Any help regarding this will be appreciated

2 Answers

Answers 1

If you're looking to run a server in the Google Cloud, you must remember that Unity is just a piece of software, with full access to C#. This means you can utilize the entirety of the .NET framework, Mono, .NET Core, or whatever other C# libraries to accomplish whatever task you wish.

The simplest method of getting a server running, as I've seen it done before, is to use NodeJS. NodeJS is pretty fast, and I had a friend have working multiplayer using NodeJS alone. This means that you can get a backend working without much effort, ASSUMING you do not have to also have a website pulling data off of this. This would be where I'd start with that endeavour.

If you want to stick to C#, there's another alternative called ASP.Net Core. Microsoft recently released something called .NET Core, which means that you can run .NET (sort of) code on Linux, Mac, etc. Either way, with C#, you're going to be needing to make post requests via Unity to the web server, and process the returned JSON.

And finally, if you want to stick to C#, but not use ASP.Net core, you can always just use sockets, or write your entire web server from scratch using a technology of your choice.

But, the most important thing you should take away from this is that Unity is capable of running C# code as software itself, outside of the game. All .NET code is accessible, for example, if .NET is installed on the machine. This means you could, theoretically, set it up with Mono, and use Mono instead. Unity is just an engine processing graphics, physics, and input entirely for you, with a layer that exposes C# scripting for you (where C# is an intermediate language).

Best of luck.

Answers 2

You're basically asking "how to cloud host my game server" here which is an extremely complex question.

The process is exactly the same as you did with AWS in the google infrastructure.

Read More